【问题标题】:Same header & footer in all WPF windows所有 WPF 窗口中的相同页眉和页脚
【发布时间】:2020-10-07 13:07:38
【问题描述】:

在我的项目中,所有窗口都有相同的页眉和页脚(我在这个项目中有超过 20 个 wpf 窗口),只有内容发生了变化。这是 WPF 项目。如果它是一个 asp.net,我在其中使用了母版页。

现在我复制粘贴页眉和页脚所有窗口。如果 Header 需要任何小的更改,我必须在所有 Windows 标题中进行。有什么解决办法吗?

【问题讨论】:

    标签: wpf window


    【解决方案1】:

    我不是 100% 确定“所有窗口”是什么意思,但一个好的方法是拥有一个 header 和一个 footer 用户控件。

    您可以随意设置它们(文字、颜色等), 然后,在你的所有窗口中,你可以有一个包含 3 个元素的网格,stackpanel、dockpanel,任何你想要的,其中将有 header,然后是你的 content,最后是你的 footer


    编辑: 根据评论:而不是这样:

    <Window ...>
        <StackPanel>
            <Label>one</Label>
            <Label>two </Label>
            <Label>three</Label>
        </StackPanel>
    </Window>
    

    您可以拥有一个 UserControls(假设称为 HeaderControl),然后您需要做的就是

    1. 添加命名空间以便您使用它。
    2. 像添加任何其他控件一样添加它。
    3. 享受可重用性。

    步骤说明:

    1. 将此与其余的 xmlns.... 定义一起添加到您的窗口中:
      xmlns:controls="clr-namespace:WpfApplication1"

    2. 将第一个控件从标签更改为我们的资源:
      而不是 &lt;Label&gt;one&lt;/Label&gt; 写:&lt;controls:HeaderControl /&gt;

    【讨论】:

    • 所有窗口意味着在我的 WPF 项目中,我使用了更多的 25 个 WPF 窗口。你已经知道 wpf 有窗口和页面吗?
    • :) ...您使用 1 页并交换其内容?您使用不同的实际窗口打开和关闭?这就是问题......无论如何,答案都是一样的。拥有您使用页眉/内容/页脚定义的 1 个控件。然后只需交换内容,其余部分留在原地
    • 您使用不同的实际窗口打开和关闭?是的先生。现在我这样做了。这是最坏的主意吗?如何使用 header-content-footer 进行控制以及如何交换内容?
    • MVVM 是一种从 MS 开始并与 WPF 配合得很好的设计模式。学起来要花点功夫,但是一旦学会了,还是蛮甜的,好处也不少。没什么可做的,但我猜想读一下……
    • MVVM 绝对值得学习,但这纯粹是 View 的责任,没必要把 ViewModel 带到这里。请参阅我的答案,该答案演示了我希望满足您的要求并且可以在有或没有 mvvm 的情况下使用的解决方案。
    【解决方案2】:

    第 1 步:在 app.xaml 或共享 ResourceDictionary 中使用页眉和页脚定义窗口样式。

    <Style x:Key="HeaderFooterWindowStyle" TargetType="Window">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Grid Background="{TemplateBinding Background}">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
    
                        <!-- Header -->
                        <Border Grid.Row="0" Background="Red">
                            <TextBlock Text="Header"/>
                        </Border>
    
                        <!-- Body -->
                        <ContentPresenter Grid.Row="1"/>
    
                        <!-- Footer -->
                        <Border Grid.Row="2" Background="Red">
                            <TextBlock Text="Footer"/>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    第 2 步:将样式设置为 windows。

    Style="{StaticResource HeaderFooterWindowStyle}"
    

    【讨论】:

    • 我试过这个。它非常简单。我有一个疑问,如何在窗口中设置 ContentPresenter condent?
    • ContentPresenter 这里用于显示所有窗口的控件。你不需要设置它的内容
    • 哦!我希望页脚文本块作为品牌,我与动画有关。但我想根据 MYSQL 数据库更改文本块文本。所以我想访问这个文本块,我已将文本块命名为 footer1,但我无法在 mainpage.xaml.cs 页面中获取它。我怎样才能获得此控制访问权限?
    • 您可以通过在 OnApplyTemplate 中调用 this.GetTemplateChild("F1") 来获取 Footer TextBlock(其中 F1 是 TextBlock 名称)。但是不建议以这种方式访问​​控件。如果您只想更改其文本,请将 Text 属性绑定到某个东西。
    【解决方案3】:

    为什么不创建您自己的从常规窗口派生的“MyWindow”类?

    这是一种相当普遍的做法,而您需要覆盖/自定义标准 Window 组件。有了新组件后,您应该编写一个自定义模板,以便任何内容都将以您想要的方式显示。

    看看这里:http://msdn.microsoft.com/en-us/library/aa969824(v=vs.110).aspx

    【讨论】:

    • 我可能明白我的答案不是最好的,但是……为什么要被否决?
    • 在这里,有一个upvote mate :) 我认为如果你想让所有窗口都具有相同的页眉和页脚,这实际上是更好的解决方案......正如你所说,从Window派生,然后简单地添加这个基类中的项目在适当的事件上,然后所有新的 xaml 窗口都将属于这种类型......很好的解决方案 [虽然你的喜欢不起作用]
    • 如果你只想为任何控件添加一些视觉效果,你应该编辑它的模板。您可以为此使用样式。仅当您需要添加一些属性或功能时才创建新控件。你为什么要创建 MyWindows 类,什么都不改变代码,然后定义 xaml 模板,而你可以为 windows 创建新样式并编辑 xaml 模板。
    • @Liero,有 DataTemplates、ControlTemplates 和 Styles:每个都有自己的用途。 DataT 依赖于数据,所以情况并非如此。 ControlT 可以使用,但对任何实例都有效且不易修改。恕我直言,样式是最后的改进,例如颜色、字体等。相反,Window 的派生可以让您的生活更轻松。
    • @Mario:我想你想在 MyWindow 的 ContentProperty 中定义页眉和页脚。如果您将其更改为从 MyWindow 而不是 Window 继承,那么您将如何定义 MainWindow 或任何其他 Window 的内容?如果您将任何 xaml 写入 MainWindow 或将任何内容放在 Visual Studio 的设计器表面上,页脚和页眉将被覆盖。
    【解决方案4】:

    我想您需要在每个窗口中指定页脚和页眉,但您希望具有一致的外观。

    一般来说,如果你想在内容周围添加一些可重用的视觉效果,你应该使用内容控件并编辑它的模板。

    如果您还需要为内容指定标题,您应该使用 HeaderedContentControl 并编辑它的模板。

    如果您还需要指定页脚,只需创建您自己的从 HeaderedContentControl 继承的控件并指定页脚属性。

    这里是使用的expampe:

    <controls:HeaderFooterContentControl 
        Header="Some simple header" 
        Footer="There could be xaml footer as well!>
        <Grid>
            <!--Place your content here-->
        </Grid>
    </controls:HeaderFooterContentControl>
    

    和实施:

    public class HeaderFooterContentControl : HeaderedContentControl
    {
        public object Footer
        {
            get { return (object) GetValue(FooterProperty); }
            set { SetValue(FooterProperty, value); }
        }
    
        public static readonly DependencyProperty FooterProperty = DependencyProperty.Register("Footer", typeof (object), typeof (HeaderFooterContentControl));
    }
    

    和模板:

    <Style TargetType="controls:HeaderFooterContentControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="controls:HeaderFooterContentControl">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
    
                        <Border Grid.Row="0" Background="White">
                            <ContentControl Content="{TemplateBinding Header}"  Foreground="Red"
                                            ContentTemplate=""   />
                        </Border>
    
                        <Border Grid.Row="1" Background="Red">
                            <ContentControl Content="{TemplateBinding Content}" Foreground="White"
                                            ContentTemplate="{TemplateBinding ContentTemplate}"
                                            ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"/>
                        </Border>
    
                        <Border Grid.Row="2" Background="White">
                            <ContentControl Content="{TemplateBinding Footer}" Foreground="Red"  />
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    请注意,这与 MVVM 无关,但由于 Header 和 Footer 是依赖属性,因此可以在任何 MVVM 场景中轻松使用。

    如果可能的话,我肯定会避免绑定到 ControlTemplate 中的视图模型属性。

    【讨论】:

      猜你喜欢
      • 2016-01-24
      • 1970-01-01
      • 2018-10-10
      • 2012-04-26
      • 2016-04-30
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      • 2017-07-13
      相关资源
      最近更新 更多