【问题标题】:WPF Events in ResourceDictionary for a Window templateWindow 模板的 ResourceDictionary 中的 WPF 事件
【发布时间】:2011-08-10 18:46:48
【问题描述】:

我目前正在尝试实现 Metro 风格的窗口。
所以我在 ResoruceDictionary 中创建了以下样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!-- Brushes -->
<SolidColorBrush x:Key="BackgroundColor" Color="#FFFFFFFF" />

<!-- Buttons -->
<Style x:Key="MetroControlBoxButton" TargetType="Button">
    <Setter Property="Background" Value="{StaticResource BackgroundColor}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- Windows -->
<Style x:Key="MetroWindow" TargetType="Window">
    <Setter Property="UseLayoutRounding" Value="True" />
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="ResizeMode" Value="NoResize" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Window">
                <Grid Background="{StaticResource BackgroundColor}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="6" />
                        <RowDefinition Height="24" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="24" />
                        <RowDefinition Height="6" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="6" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="6" />
                    </Grid.ColumnDefinitions>

                    <Rectangle Name="topLeftBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="0" />
                    <Rectangle Name="topCenterBorderRectangle" Fill="Orange" Grid.Row="0" Grid.Column="1" />
                    <Rectangle Name="topRightBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="2" />
                    <Rectangle Name="middleLeftBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" />
                    <Rectangle Name="middleRightBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="2" />
                    <Rectangle Name="bottomLeftBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="0" />
                    <Rectangle Name="bottomCenterBorderRectangle" Fill="Orange" Grid.Row="4" Grid.Column="1" />
                    <Rectangle Name="bottomRightBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="2" />

                    <Rectangle Name="statusBarRectangle" Fill="Yellow" Grid.Row="3" Grid.Column="1" />

                    <Grid Grid.Row="1" Grid.Column="1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="28" />
                            <ColumnDefinition Width="28" />
                            <ColumnDefinition Width="28" />
                        </Grid.ColumnDefinitions>

                        <Rectangle Name="dragRectangle" Fill="Yellow" Grid.Row="0" Grid.Column="1" />
                        <Button Name="minimizeButton" Content="_" Grid.Row="0" Grid.Column="2" Style="{StaticResource MetroControlBoxButton}" />
                        <Button Name="maximizeButton" Content="[]"  Grid.Row="0" Grid.Column="3" Style="{StaticResource MetroControlBoxButton}" />
                        <Button Name="closeButton" Content="X" Grid.Row="0" Grid.Column="4" Style="{StaticResource MetroControlBoxButton}" />
                    </Grid>

                    <ContentPresenter Grid.Row="2" Grid.Column="1" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

我的问题是我想实现控制框按钮(最小化、最大化和关闭)。
我可以创建三个按钮,将它们对齐到右上角。 但由于我的风格在 ResourceDictionary 中,我不知道如何实现点击事件。

调整大小和拖动窗口也是如此。我知道如何拖动和调整窗口大小,但我需要将其链接到 Window_MouseLeftButtonDown 事件,但我不知道如何将其链接到模板中。

我看到我“可以”创建一个类并将我的代码放在这里:
Is it possible to set code behind a resource dictionary in WPF for event handling?
但这似乎不是一个好方法。

我认为我可以创建一个 MetroWindow 并让我的其他 Windows 继承它。 但是 WPF 不支持视觉继承。

那么最佳实践是什么?这样可以在整个应用程序中的多个窗口上重复使用我的 Window 模板。

谢谢,
天狼星尼克

【问题讨论】:

    标签: wpf events event-handling resourcedictionary


    【解决方案1】:

    我对按钮问题有点困惑。即使您在样式的 Template 属性中创建了一个按钮,您仍然需要将该样式应用于我在您的示例中没有看到的按钮对象。点击事件或命令将被添加到按钮元素。

    例如:

    <Button x:Name="testButton" Style="{StaticResource MetroControlBoxButton}" ... />
    

    更新:

    要从控件模板绑定到 Window 的 DataContext 中的命令,您可能需要将此元素添加到 Button 定义中:

    Command="{Binding Path=DataContext.ClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
    

    【讨论】:

    • 我已经更新了我的原始帖子以添加按钮。那么我的 closeButton 如何执行 Close();模板内的方法?
    • 即使它在模板中,由于您已经定义了按钮,因此您可以执行命令绑定来执行位于 Window 的 DataContext 中的操作。我相信这是您可以执行此操作的唯一方法,因为如果在 ResourceDictionary 中定义了该事件,则不会找到该事件。如果我错了,请有人纠正我。我在下面更新了我的答案以显示一个示例。
    • 从您的回答中,我意识到我缺少一些知识。经过一番研究,我发现我对 MVVM 一无所知!所以我制作了一个 MetroWindowViewModel 并且能够成功绑定命令。但是有一个问题,如果我想在多个 Windows 上使用我的 Window 模板,我是否需要让每个新的 Windows ModelView 都继承我的 MetroWindowModelView?
    • 您不必强制继承该 ViewModel。您可以将它的另一个实例甚至单独的 ViewModel 全部附加在一起,只要它具有同名的 Command 以便 Window 可以绑定到它。
    • @SiriusNik 我遇到了和你一样的问题,现在你能给出答案吗? :D。我搜索了很多但没有结果。 :)
    猜你喜欢
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多