0

我是 WPF 的新手,但一直在尝试组合一个演示应用程序来说明我们的产品如何通过从 Forms MDI 迁移来改进。

我有一个 TabControl 模板,因为没有更好的名称,我在这里称之为“TabbedPanel”。此 TabbedPanel 有两个附加按钮:“全屏”和“关闭”。在下面的代码中,您可以看到我尝试了两种不同的方法来将这些按钮的可见性绑定到一个属性,但都没有按预期工作。

<UserControl x:Class="myApp.TabbedPanel"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <ControlTemplate x:Key="TabControlControlTemplate1" TargetType="{x:Type TabControl}">
        <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
            <Grid.Background>
                <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
                    <LinearGradientBrush.RelativeTransform>
                        <TransformGroup>
                            <ScaleTransform CenterY="0.5" CenterX="0.5"/>
                            <SkewTransform CenterY="0.5" CenterX="0.5"/>
                            <RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>
                            <TranslateTransform/>
                        </TransformGroup>
                    </LinearGradientBrush.RelativeTransform>
                    <GradientStop Color="#FFD5D5D6" Offset="0.5"/>
                    <GradientStop Color="#FF646464" Offset="1"/>
                    <GradientStop Color="#FF606060"/>
                </LinearGradientBrush>
            </Grid.Background>
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="ColumnDefinition0"/>
                <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                <RowDefinition x:Name="RowDefinition1" Height="*"/>
            </Grid.RowDefinitions>
            <TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="True" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
            <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
            </Border>
            <Button Name="btnFullscreen" Content="FULLSCREEN" HorizontalAlignment="Right" Height="23" Margin="0,0,25.863,0" VerticalAlignment="Top" Width="Auto" FontWeight="Bold" Click="btnFullscreen_Click" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FullscreenButtonVisibility}">
                <Button.Background>
                    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                        <GradientStop Color="#FF99945E" Offset="0"/>
                        <GradientStop Color="#FFEBEBEB" Offset="0.569"/>
                        <GradientStop Color="#FFDDDDDD" Offset="0.259"/>
                        <GradientStop Color="#FFB4B04D" Offset="1"/>
                    </LinearGradientBrush>
                </Button.Background>
            </Button>
            <Button Name="btnClose" Content="X" HorizontalAlignment="Right" Height="23" Margin="0" VerticalAlignment="Top" Width="25.863" BorderBrush="#FF2C0101" Foreground="White" FontWeight="Bold" Click="btnClose_Click" Visibility="{Binding Mode=TwoWay, Path=CloseButtonVisibility}">
                <Button.Background>
                    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                        <GradientStop Color="#FF850303" Offset="0"/>
                        <GradientStop Color="#FFF00000" Offset="0.5"/>
                        <GradientStop Color="#FF720707" Offset="0.004"/>
                        <GradientStop Color="#FF970000" Offset="1"/>
                    </LinearGradientBrush>
                </Button.Background>
            </Button>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="TabStripPlacement" Value="Bottom">
                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
            </Trigger>
            <Trigger Property="TabStripPlacement" Value="Left">
                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
            </Trigger>
            <Trigger Property="TabStripPlacement" Value="Right">
                <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</UserControl.Resources>
    <TabControl Name="tabitems" Background="white" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Template="{DynamicResource TabControlControlTemplate1}">
        <TabControl.Resources>
            <Style TargetType="TabItem">
                <Setter Property="AllowDrop" Value="True"/>
                <EventSetter Event="PreviewMouseMove" Handler="TabItem_PreviewMouseMove"/>
                <EventSetter Event="Drop" Handler="TabItem_Drop"/>
            </Style>
            <Style TargetType="TabControl">
                <Setter Property="AllowDrop" Value="True"/>
                <EventSetter Event="PreviewMouseMove" Handler="TabItem_PreviewMouseMove"/>
                <EventSetter Event="Drop" Handler="TabItem_Drop"/>
            </Style>
        </TabControl.Resources>
    </TabControl>

下面显示了 C# 代码的相关部分。我从 INotifyPropertyChanged 继承并实现了两个属性的接口:CloseButtonVisibility 和 FullscreenButtonVisibility。

public partial class TabbedPanel : UserControl, INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    public TabbedPanel()
    {
        InitializeComponent();
    }

    public event RoutedEventHandler Close;
    public event RoutedEventHandler Fullscreen;

    private Visibility closeButtonVisibility;
    public Visibility CloseButtonVisibility
    {
        get { return closeButtonVisibility; }
        set 
        {
            SetField(ref closeButtonVisibility, value, "CloseButtonVisibility");
        }
    }

    private Visibility fullscreenButtonVisibility;
    public Visibility FullscreenButtonVisibility
    {
        get { return fullscreenButtonVisibility; }
        set
        {
            SetField(ref fullscreenButtonVisibility, value, "FullscreenButtonVisibility");
        }
    }

    public ItemCollection Tabs
    {
        get { return tabitems.Items; }
    }

然后,我在 MainWindow.xaml 的以下代码中使用 TabbedPanel。然后将 FullscreenButtonVisibility 和 CloseButtonVisibility 初始化为 Visibility.Hidden。

<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <local:TabbedPanel Grid.Row="0" FullscreenButtonVisibility="Hidden" CloseButtonVisibility="Hidden">
            <local:TabbedPanel.Tabs>
                <TabItem Header="Top">
                    <Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="Artwork\ImageTop.JPG"/>
                </TabItem>
                <TabItem Header="Left">
                    <Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="Artwork\ImageBottom.BMP"/>
                </TabItem>
                <TabItem Header="Bottom">
                    <Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="Artwork\ImageLeft.JPG"/>
                </TabItem>
                <TabItem Header="Right">
                    <Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="Artwork\ImageRight.JPG"/>
                </TabItem>
            </local:TabbedPanel.Tabs>
        </local:TabbedPanel>
    </Grid>

使用它,我希望“全屏”和“关闭”按钮开始时是不可见的,但它们会显示出来。我很确定我可以在 C# 中通过程序设置它们的可见性,但通过 XAML 这样做会更干净。另外,我很确定我在这里错过了一些让我失望的根 WPF 概念,但我已经自学了几天......任何帮助将不胜感激。

4

0 回答 0