【问题标题】:How to reuse layouts in WPF如何在 WPF 中重用布局
【发布时间】:2011-03-01 14:29:00
【问题描述】:

我正在尝试创建一个带有标签的应用程序,其中每个标签都有一个按钮区域和一个视图区域。

现在每个选项卡基本上都有相同的布局,只是布局中的内容不同,我希望能够重用相同的布局,这样我就不必在很多地方进行更改(这只是不好的编程)。我可以使用资源或样式来完成此操作吗?

如果可能,请提供一个灯光代码示例。

编辑:我决定添加一个我正在尝试做的示例,因为我仍然没有得到它。

在每个 TabItem 下我试图重新创建这个网格(它有点复杂,但你明白了):

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="200"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Border Margin="10"
                            BorderBrush="{StaticResource MediumColorBrush}"
                            CornerRadius="10"
                            BorderThickness="2"
                            Grid.Row="0">

               <!-- First content goes here -->

        </Border>

        <Border Margin="10"
                            BorderBrush="{StaticResource MediumColorBrush}"
                            CornerRadius="10"
                            BorderThickness="2"
                            Grid.Row="1">

               <!-- Second content goes here -->

        </Border>

    </Grid>

你也可以看到这两个边框是一样的。现在我需要在我的 cmets 所在的位置放置一些内容占位符。我不想在资源字典中声明这个网格布局,然后在我使用它的地方将单独的内容放入每个边框。

我可能有很多 TabItem,因此重复此代码不是一个好主意,并且每个 Tab 页面在 2 个占位符中都有不同的内容。

我可以使用

<ContentPresenter Content="{Binding}" />

事情,但只有 1 个内容,当会有更多内容时会发生什么。

【问题讨论】:

    标签: wpf layout styles resourcedictionary


    【解决方案1】:

    英戈,

    代码始终在 MSDN 上可用。检查这个:UserControlCustom controlsDataTemplates

    以下是每种方法的一些示例。为简单起见,我们假设您要复制的布局是一行带有绿色前景的文本(实际上它可能真的不同,但您明白了)。


    1.用户控制

    Xaml:

    <UserControl x:Class="WpfApplication1.GreenTextUserControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <TextBlock x:Name="txt" Foreground="Green"/>
    </UserControl>
    

    C#:

    using System.Windows.Controls;
    
    namespace WpfApplication1
    {
      public partial class GreenTextUserControl : UserControl
      {
        public string Text
        {
          get { return txt.Text;}
          set { txt.Text = value; }
        }
    
        public GreenTextUserControl()
        {
          InitializeComponent();
        }
      }
    }
    

    选项卡控件

    <TabControl>
      <TabItem Header="Tab 1">
        <loc:GreenTextUserControl Text="This is Tab 1"/>
      </TabItem>
      <TabItem Header="Tab 2">
        <loc:GreenTextUserControl Text="This is Tab 2"/>
      </TabItem>
      <TabItem Header="Tab 3">
        <loc:GreenTextUserControl Text="This is Tab 3"/>
      </TabItem>
    </TabControl>
    

    2。自定义控件

    C#:

      public class GreenTextBlock : TextBlock
      {
        public GreenTextBlock()
        {
          Foreground = Brushes.Green;
        }
      }
    

    TabControl:

    <TabControl>
      <TabItem Header="Tab 1">
        <loc:GreenTextBlock Text="This is Tab 1"/>
      </TabItem>
      <TabItem Header="Tab 2">
        <loc:GreenTextBlock Text="This is Tab 2"/>
      </TabItem>
      <TabItem Header="Tab 3">
        <loc:GreenTextBlock Text="This is Tab 3"/>
      </TabItem>
    </TabControl>
    

    如果您的布局比文本块更复杂,自定义控件也允许您在 XAML 中定义它,但它与 UserControls 不同。


    3.数据模板

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            xmlns:System="clr-namespace:System;assembly=mscorlib" 
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
        <x:Array x:Key="GreenText" Type="{x:Type System:String}">
          <System:String>This is Tab 1</System:String>
          <System:String>This is Tab 2</System:String>
          <System:String>This is Tab 3</System:String>
        </x:Array>
    
        <!--Tab item content data template-->
        <DataTemplate x:Key="GreenTextTemplate">
          <TextBlock Text="{Binding}" Foreground="Green"/>
        </DataTemplate>
      </Window.Resources>
        <Grid>
        <TabControl ItemsSource="{StaticResource GreenText}">
          <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
              <Setter Property="ContentTemplate" Value="{StaticResource GreenTextTemplate}"/>
            </Style>
          </TabControl.ItemContainerStyle>
        </TabControl>
      </Grid>
    </Window>
    

    就是这样:)。希望对您有所帮助。

    【讨论】:

    • 谢谢你,我仍然对 WPF 感到困惑。现在刚刚意识到创建自己的类的可能性,该类继承自 TabItem 但已准备好结构。不确定这是否可行,因为我不知道如何将内容添加到布局中。
    • 好的,发现你不能继承 Xaml 类,所以这对我没有用。你提到的所有文章都是关于自定义控件而不是重用布局,如果你的意思是我可以自定义 TabItem 或其他东西来完成这项工作,我没有看到它。
    • 自定义 TabItem 对我来说似乎不合适(尽管您可以通过自定义控件)。相反,您可以创建一个用户控件并将其放在每个 TabItem 中。更优雅的解决方案是创建 DataTemplate 并将其用作 TabControl 的 ItemTemplate ...
    • 好吧,肯定有一些误解,或者我只是愚蠢的。你提到了用户控件,你最初给了我一个应该如何制作用户控件的链接,但我只是不知道这在这种情况下有什么用处。您还提到了 DataTemplate,我可以理解的是,围绕绑定数据这不是问题所在。我不想在几个 tabItems 上重复使用相同的主布局,而不必重复代码。如果您所暗示的确实可以按我的需要进行,我也不明白如何。有没有什么地方的例子。
    • 嘿英戈,不要对自己太苛刻。对不起,令人困惑的答案。我已经扩展了它。看看吧。
    【解决方案2】:

    TabItem 是一个 ContentControl,它允许任何子内容,但也允许对内容进行模板化,这正是您想要做的。您可以使用这样的 DataTemplate 来进行共享布局。 ContentPresenter 是每个 TabItem 不同内容的占位符。

    <DataTemplate x:Key="ButtonViewerTemplate">
        <DockPanel>
            <Button DockPanel.Dock="Bottom" Content="OK"/>
            <Button DockPanel.Dock="Bottom" Content="Cancel"/>
            <Border Background="Aqua" BorderBrush="Red" BorderThickness="2" Padding="5">
                <ContentPresenter Content="{Binding}" />
            </Border>
        </DockPanel>
    </DataTemplate>
    

    要使用模板,只需将其设置为每个 TabItem 的 ContentTemplate。这适用于从 ContentControl 派生的任何内容。

    <TabControl>
        <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Some Buttons">
            <UniformGrid>
                <Button Content="XXXXX"/>
                <Button Content="XXXXX"/>
                <Button Content="XXXXX"/>
                <Button Content="XXXXX"/>
            </UniformGrid>
        </TabItem>
        <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="All Blue">
            <Border Background="Blue" MinHeight="50"/>
        </TabItem>
        <TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Image">
            <Image Source="http://i.msdn.microsoft.com/Platform/Controls/StoMastheadMSDN/resources/logo_msdn.png"/>
        </TabItem>
    </TabControl>
    

    【讨论】:

    • 好吧,假设我在 TabItem 中有一个网格,我将在 DataTemplate 中定义网格。但是,如果我不想在选项卡之间以不同的方式将内容添加到网格中怎么办。也许我应该定义一个网格样式并在每个网格上使用它,但我不确定如何在网格样式中定义行和列的大小。
    • DataTemplate 和 TabItem 内容都可以包含任何内容,包括像 Grid 这样的面板。模板项目之间需要有所不同的任何内容都可以放在 TabItem 内容中。
    • 好的,您的意思是,您在第二个 codeWindow 中创建的 UniformGrid 将被放入第一个窗口中的 Aqua 颜色边框中,替换内容/绑定家伙?
    • 没错。这可以是您想要的任何东西:Control、Panel、UserControl 等。
    • 好的,但是如果您有 2 个或更多内容进入单独的 GridRows,就像我上面的示例一样?
    猜你喜欢
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2014-12-03
    • 2012-12-10
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多