在BasedOn样式

时间:2018-05-14 19:06:19

标签: c# wpf xaml user-interface styles

我正在接近WPF(特别是我正在使用MVVM),并且我正在尝试创建将在整个应用程序中使用的自定义窗口样式。我想要做的是创建一个基本样式,定义窗口颜色,边框,图标,标题等。窗口可以调整大小或对话框,所以我使用WindowChrome设置"可调整大小的窗口&# 34;默认情况下,它具有最小化,最大化和关闭按钮,并且实际上可以调整大小。对于Login窗口,我希望有一个使用基本样式的窗口,但是用户无法调整大小或最大化它,因此最大化按钮根本不可见。我一直在研究BasedOn样式,我可以成功覆盖属性,但我无法定义哪些按钮可以在窗口内显示或不可见。所以我要做的就是更改嵌套的UI控件(在这种情况下为StackPanel)。

这是我创建的基本样式,目前包含所有窗口属性和窗口按钮(我试着尽可能地评论它):

<ControlTemplate TargetType="{x:Type Window}" x:Key="DefaultWindowsTemplate">

    <!-- The outer border of the Window -->
    <Border Padding="{Binding OuterMarginSizeThickness, FallbackValue=10}">

        <!-- The inner border of the Window and the Window itself, from the contour line to the shadow -->
        <Grid>
            <Border CornerRadius="{Binding WindowCornerRadius}" 
                    BorderBrush="{StaticResource AlizarinBrush}" 
                    BorderThickness="{Binding OutlineBorderThickness, FallbackValue=1}"
                    Background="{StaticResource VoidnessBrush}">
                <Border.Effect>
                    <DropShadowEffect Color="{StaticResource Voidness}" ShadowDepth="0" Opacity="1"/>
                </Border.Effect>
            </Border>

            <!-- The Container grid, composed by the title bar and the content area -->
            <Grid>

                <!-- Rows definition -->
                <Grid.RowDefinitions>
                    <RowDefinition Height="{Binding TitleHeight, FallbackValue=30}"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <!-- Title bar row that contains icon, title and window buttons -->
                <Grid Margin="{Binding TitleHeightMargin}" 
                      Background="{StaticResource VoidnessBrush}" 
                      Grid.Row="0" 
                      Panel.ZIndex="1"
                      >

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>

                    </Grid.ColumnDefinitions>

                    <!-- Window icon -->
                    <Button Margin="5 5 0 0" 
                            Style="{StaticResource WindowIconButtonStyle}" 
                            Command="{Binding MenuCommand}">

                        <Image Source="/Images/Logos/khm_logo_titlebar.png"/>

                    </Button>

                    <!-- Window title -->
                    <TextBlock Grid.Column="1"
                               Foreground="{StaticResource ConcreteBrush}"
                               Margin="15 5 0 0"
                               TextAlignment="Center"
                               VerticalAlignment="Center"
                               HorizontalAlignment="Left"
                               Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title, FallbackValue='Window Title'}"/>

                    <!-- Window buttons - THIS IS THE CONTROL I WANT TO DEFINE INSIDE 'BASED ON' STYLES, WHERE I WILL NOT HAVE THE MAXIMIZE BUTTON -->
                    <StackPanel Grid.Column="2"
                                Orientation="Horizontal">

                        <Button Style="{StaticResource WindowButtonsStyle}"
                                Content="0"
                                Command="{Binding MinimizeCommand}"/>

                        <ToggleButton Style="{StaticResource MaximizeWindowButtonStyle}"
                                      Command="{Binding MaximizeCommand}"/>

                        <Button Style="{StaticResource WindowCloseButtonStyle}"
                                Content="r"
                                Command="{Binding CloseCommand}"/>

                    </StackPanel>

                </Grid>

                <!-- The Window content -->
                <Grid Margin="1 5 0 0" Grid.Row="1">
                    <ContentPresenter/>
                </Grid>

            </Grid>
        </Grid>
    </Border>

</ControlTemplate>

<Style TargetType="Window" x:Key="DefaultWindowsStyle">
    <Setter Property="Template" Value="{StaticResource DefaultWindowsTemplate}"/>
    <Setter Property="MinWidth" Value="{Binding WindowMinWidth}"/>
    <Setter Property="MinHeight" Value="{Binding WindowMinHeight}"/>
    <Setter Property="WindowStyle" Value="None"/>
    <Setter Property="AllowsTransparency" Value="True"/>
</Style>

然后我开始编辑基本样式,如下所示(当然在另一个XAML文件中):

<Style TargetType="Window" x:Key="DialogWindowsStyle" BasedOn="{StaticResource DefaultWindowsStyle}">
    <!-- REMOVE THE MAXIMIZE BUTTON INSIDE THE NESTED STACK PANEL -->
</Style>

那么在使用相同样式的同时编辑部分UI的正确方法是什么?

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我将定义布尔附加属性local:WindowExt.ShowMaximizeButton等,默认值为true。在ControlTemplate中,我将这些应用程序应用于带有TemplateBindings的按钮,并通过样式设置器(或直接在XAML中的Window元素上)设置它们。

以下是ShowMaximizeButton的示例;其他人用不同的名字是一样的。复制并粘贴依赖项属性定义时,请注意在每个出现的位置更新属性名称。我使用片段来创建它们,以尽量减少粗心错误。

public static class WindowExt
{
    public static bool GetShowMaximizeButton(Window obj)
    {
        return (bool)obj.GetValue(ShowMaximizeButtonProperty);
    }

    public static void SetShowMaximizeButton(Window obj, bool value)
    {
        obj.SetValue(ShowMaximizeButtonProperty, value);
    }

    public static readonly DependencyProperty ShowMaximizeButtonProperty =
        DependencyProperty.RegisterAttached("ShowMaximizeButton", typeof(bool), typeof(WindowExt),
            new PropertyMetadata(true));
}

确保它位于定义窗口控件模板之前的某个位置,在同一资源字典中:

    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />

窗口控制模板中的最大化按钮。除了将这些适当绑定的可见性属性添加到按钮之外,不会对控件模板进行任何更改。注意Binding路径中的parens;这些是至关重要的,因为它是单个属性的多部分标识符。

<ToggleButton 
    Style="{StaticResource MaximizeWindowButtonStyle}"
    Command="{Binding MaximizeCommand}"
    Visibility="{TemplateBinding local:WindowExt.ShowMaximizeButton, Converter={StaticResource BooleanToVisibilityConverter}}"
    />

并在窗口样式中使用:

<Style TargetType="Window">
    <Setter Property="local:WindowExt.ShowMaximizeButton" Value="True" />
</Style>

请注意,附加属性是控件本身的依赖项属性,与任何DataContexts或viewmodel无关。

相关问题