2010-05-21 99 views
19

我有一个带有选项卡控件和页面数的选项卡 - 选项卡项。每个标签项目具有相同的网格布局 - 6行4列。现在,每个选项卡项都包含具有行和列定义的网格,因此几乎一半的XAML都是网格的定义。如何创建可重复使用的WPF网格布局

如何在一个地方定义这个网格并在我的应用程序中重用该定义?模板?用户控制?

除了6x4,我只有两个重复的网格尺寸:8x4和6x6。

编辑:
忘了提及:网格中的控件对于每个选项卡都不相同。我只想在一些资源中定义一次网格,以便我可以在不同的标签页上重复使用它们。现在,XAML如下所示:

<TabControl> 
     <TabItem Header="Property"> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <!-- some controls here --> 
      </Grid> 
     </TabItem> 
     <TabItem Header="Style"> 
      <Grid > 
       <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition />       
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition />       
        <ColumnDefinition /> 
        <ColumnDefinition /> 
       </Grid.ColumnDefinitions> 
       <!-- some controls here --> 
      </Grid> 
     </TabItem> 

     ... and this repeats for several more tab items 

    </TabControl> 

此表格定义对表格上的每个选项卡项都重复。它让我很烦恼XAML的一半是网格定义。

有没有办法在一个地方定义这个网格,然后重用该定义?

回答

0

通常会为进入标签的数据写一个DataTemplate。该DataTemplate将包含网格。

0

如何在一个地方定义这个网格并在我的应用程序中重用该定义?模板?用户控制?

如果我是你,我会创造一个UserControl或自定义Control与重复的代码,然后只需消耗从当前的代码控制。

另一种方法是使用DataTemplateControlTemplate

TabItem创建ControlTemplate也会很好。

25

在我看来,最好的办法是使用ItemsControlItemsPanelTemplate,因为你需要为多个项目的容器:

<FrameworkElement.Resources> 
    <Style x:Key="GridItemsStyle" 
      TargetType="ItemsControl"> 
     <Setter Property="ItemsPanel"> 
      <Setter.Value> 
       <ItemsPanelTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
          <ColumnDefinition /> 
         </Grid.ColumnDefinitions> 
        </Grid> 
       </ItemsPanelTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</FrameworkElement.Resources> 
<TabControl> 
    <TabItem> 
     <ItemsControl Style="{StaticResource GridItemsStyle}"> 
      <TextBlock Grid.Row="1" Text="R1" /> 
      <TextBlock Grid.Column="1" 
         Text="C1" /> 
     </ItemsControl> 
    </TabItem> 
    <TabItem> 
     <ItemsControl Style="{StaticResource GridItemsStyle}"> 
      <TextBlock Grid.Row="2" 
         Text="R2" /> 
      <TextBlock Grid.Column="2" 
         Text="C2" /> 
     </ItemsControl> 
    </TabItem> 
</TabControl> 
+0

作品看起来很简单 – 2015-11-25 07:51:08

+0

很好的回答!这正是我所寻找的,非常感谢分享:-) – 2016-01-22 09:18:35

1

我有类似的东西。问题是你如何不把数据放入网格?

由于您一次又一次地使用相同的布局,我猜你正在向每个单元格放上类似的东西。

我为每个Tab创建了一个自定义ItemsControl,将数据放入并为ItemsControl显示网格创建了一个样式。

<Style x:Key="GridItemsStyle" 
     TargetType="ItemsControl"> 
    <Setter Property="ItemsPanel"> 
     <Setter.Value> 
      <ControlTemplate> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
        </Grid.ColumnDefinitions> 

        <ContentPresenter Content="{Binding ElementName=Cell00}" Grid.Row="0" Grid.Column="0" /> 

        <ContentPresenter Content="{Binding ElementName=Cell01}" Grid.Row="0" Grid.Column="1" /> 

        <ContentPresenter Content="{Binding ElementName=Cell10}" Grid.Row="1" Grid.Column="0" /> 


        <!-- ...And so on --> 

       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

,并在窗口

<TabControl> 
<TabItem> 
    <local:tab1 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 
<TabItem> 
    <local:tab2 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 

那么每个CustomControl自ItemsControl

继承
<ItemsControl x:Class="your_app.tab1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:your_app"> 

<ContentControl x:Name="Cell00"> 

    <!-- Some stuff here --> 

</ContentControl> 
<ContentControl x:Name="Cell01"> 

    <!-- Some stuff here --> 

</ContentControl> 
<ContentControl x:Name="Cell10"> 

    <!-- Some stuff here --> 

</ContentControl> 

这是非常相似,除了我设置ContentPresenter什么Aelij做将它绑定到一个名称并将itemsControl放入它自己的东西(可以混合b其他解决方案)。

它仍然是很多代码,但我会说你一直保存自己的所有行和列的定义,你也只需要在一个地方改变网格,如果你必须修改它。

3

或者您也可以从电网继承...

using System.Windows.Controls; 
public class AlreadySetupGrid:Grid 
{ 
    public AlreadySetupGrid() 
    { 
     for (int i = 0; i < 4; i++) 
     { 
      ColumnDefinitions.Add(new ColumnDefinition()); 
     } 
     for (int i = 0; i < 6; i++) 
     { 
      RowDefinitions.Add(new RowDefinition()); 
     } 
    } 
} 

,然后用它来代替正常的网格。

+0

这听起来像一个更好的计划,但这是我没有得到设计时间colums和行。即网格中定义的任何元素都不能正确定位 – Gurpreet 2016-07-31 18:22:05

0

你可以做到这一点,但它需要一些工作:

1)创建一个收集和附加属性是这样的:

public class ColumnDefinitions : Collection<ColumnDefinition> 
{ 
    public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached(
     "Source", 
     typeof(ColumnDefinitions), 
     typeof(ColumnDefinitions), 
     new PropertyMetadata(
      default(ColumnDefinitions), 
      OnColumnDefinitionsChanged)); 

    public static void SetSource(Grid element, ColumnDefinitions value) 
    { 
     element.SetValue(SourceProperty, value); 
    } 

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] 
    [AttachedPropertyBrowsableForType(typeof(Grid))] 
    public static ColumnDefinitions GetSource(Grid element) 
    { 
     return (ColumnDefinitions)element.GetValue(SourceProperty); 
    } 

    private static void OnColumnDefinitionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var grid = (Grid)d; 
     grid.ColumnDefinitions.Clear(); 
     var columnDefinitions = (ColumnDefinitions)e.NewValue; 
     if (columnDefinitions == null) 
     { 
      return; 
     } 

     foreach (var columnDefinition in columnDefinitions) 
     { 
      grid.ColumnDefinitions.Add(columnDefinition); 
     } 
    } 
} 

2)然后,你可以使用它作为一种资源,并在像这样的网格样式: 请注意,必须使用x:Shared="False"。如果不是相同的定义将被添加到许多导致WPF抛出的网格。

<UserControl.Resources> 
    <demo:ColumnDefinitions x:Key="SomeColumnDefinitions" x:Shared="False"> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="*" /> 
    </demo:ColumnDefinitions> 

    <Style x:Key="SomeGridStyle" TargetType="{x:Type Grid}"> 
     <Setter Property="demo:ColumnDefinitions.Source" Value="{StaticResource SomeColumnDefinitions}"></Setter> 
    </Style> 
</UserControl.Resources> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition Height="5"/> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid Style="{StaticResource SomeGridStyle}"> 
     <Rectangle Grid.Row="0" 
        Grid.Column="0" 
        Width="120" 
        Fill="Blue" /> 
     <Rectangle Grid.Row="0" 
        Grid.Column="1" 
        Fill="Yellow" /> 
    </Grid> 

    <Grid Grid.Row="2" demo:ColumnDefinitions.Source="{StaticResource SomeColumnDefinitions}"> 
     <Rectangle Grid.Row="0" 
        Grid.Column="0" 
        Width="120" 
        Fill="Blue" /> 
     <Rectangle Grid.Row="0" 
        Grid.Column="1" 
        Fill="Yellow" /> 
    </Grid> 
</Grid>