2010-05-21 104 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>