2011-03-03 88 views
16

我想知道我可以風格電網,這樣我就不需要指定如何風格的網格ColumnDefinitions在WPF

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="auto" SharedSizeGroup="SG1"/> 
    <ColumnDefinition Width="auto" SharedSizeGroup="SG2"/> 
</Grid.ColumnDefinitions> 
每次

非常感謝!

ps:我確實嘗試在Google上搜索。但我找不到任何答案。任何人都可以從谷歌找到答案,請告訴我你用什麼關鍵字搜索?有時候我很難確定搜索關鍵字的用途。

ps2:我太懶惰了,我只是打開chrome並鍵入內容並搜索。如果沒有發現,我沒有發現任何結果並來到這裏。有沒有人會在Google上搜索,然後找不到,然後打開bing.com並搜索?什麼也找不到,然後去雅虎和搜索和搜索?.....

回答

1

我相信這是不可能的,因爲您無法設置影響所有ColumnDefinition(s)的樣式。

網格不支持ControlTemplate,所以你不能用組合來完成。

我能想到的唯一的黑客就是用這兩列創建一個用戶控件並擴展網格。但那很討厭。

7

創建更改回調附加依賴屬性同步收集要素:(因爲它基本上是相同的RowDefinition支持略)

<Grid> 
    <Grid.Style> 
    <Style TargetType="Grid"> 
     <Setter Property="my:GridUtils.ColumnDefinitions"> 
     <Setter.Value> 
      <my:ColumnDefinitionCollection> 
      <ColumnDefinition Width="1*" /> 
      <ColumnDefinition Width="1*" /> 
      </my:ColumnDefinitionCollection> 
     </Setter.Value> 
     </Setter> 
    </Style> 
    </Grid.Style> 

    <Button Content="Button" /> 
    <Button Content="Button" Grid.Column="1" /> 
</Grid> 

實現:

public class GridUtils 
{ 
    public static readonly DependencyProperty ColumnDefinitionsProperty = 
     DependencyProperty.RegisterAttached("ColumnDefinitions", typeof (ColumnDefinitionCollection), 
              typeof (GridUtils), 
              new PropertyMetadata(default(ColumnDefinitionCollection), 
                    OnColumnDefinitionsChanged)); 

    private static void OnColumnDefinitionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs ev) 
    { 
     var grid = (Grid) d; 
     var oldValue = (ColumnDefinitionCollection) ev.OldValue; 
     var newValue = (ColumnDefinitionCollection) ev.NewValue; 
     grid.ColumnDefinitions.Clear(); 
     if (newValue != null) 
      foreach (var cd in newValue) 
       grid.ColumnDefinitions.Add(cd); 
    } 

    public static void SetColumnDefinitions(Grid element, ColumnDefinitionCollection value) 
    { 
     element.SetValue(ColumnDefinitionsProperty, value); 
    } 

    public static ColumnDefinitionCollection GetColumnDefinitions(Grid element) 
    { 
     return (ColumnDefinitionCollection) element.GetValue(ColumnDefinitionsProperty); 
    } 
} 

public class ColumnDefinitionCollection : List<ColumnDefinition> {} 
+0

這樣會導致性能下降,因爲直到完成初始佈局階段後纔會執行。 – 2014-02-14 17:13:22

+0

你可以擴展嗎?我做了一些跟蹤,並且在Grid元素的任何Measure/Arrange/LayoutUpdated方法/事件之前執行了「OnColumnDefinitionChanged」。它也不會影響它們執行的次數。 – 2014-02-15 01:35:51

+0

我收到錯誤消息:''value'已經屬於另一個'ColumnDefinitionCollection'。所以我可能需要創建一個ColumnDefinition的副本。 – 2014-03-26 10:55:23

22

這一直是我的一個忌諱到必須寫出RowDefinitionsColumnDefinitions,所以有一天我厭倦了它,並寫了一些attached properties可用於這種事情。

現在不是寫我Grid的定義是這樣的:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
</Grid> 

我可以使用

<Grid local:GridHelpers.RowCount="6" 
     local:GridHelpers.StarRows="5" 
     local:GridHelpers.ColumnCount="4" 
     local:GridHelpers.StarColumns="1,3"> 

</Grid> 

它只允許Auto*大小,但大多數時候這一切我使用。對於動態

它還支持綁定尺寸的網格

<Grid local:GridHelpers.RowCount="{Binding RowCount}" 
     local:GridHelpers.ColumnCount="{Binding ColumnCount}" /> 

這裏的情況下,代碼的副本,該網站不斷下降:

public class GridHelpers 
{ 
    #region RowCount Property 

    /// <summary> 
    /// Adds the specified number of Rows to RowDefinitions. 
    /// Default Height is Auto 
    /// </summary> 
    public static readonly DependencyProperty RowCountProperty = 
     DependencyProperty.RegisterAttached(
      "RowCount", typeof(int), typeof(GridHelpers), 
      new PropertyMetadata(-1, RowCountChanged)); 

    // Get 
    public static int GetRowCount(DependencyObject obj) 
    { 
     return (int)obj.GetValue(RowCountProperty); 
    } 

    // Set 
    public static void SetRowCount(DependencyObject obj, int value) 
    { 
     obj.SetValue(RowCountProperty, value); 
    } 

    // Change Event - Adds the Rows 
    public static void RowCountChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     if (!(obj is Grid) || (int)e.NewValue < 0) 
      return; 

     Grid grid = (Grid)obj; 
     grid.RowDefinitions.Clear(); 

     for (int i = 0; i < (int)e.NewValue; i++) 
      grid.RowDefinitions.Add(
       new RowDefinition() { Height = GridLength.Auto }); 

     SetStarRows(grid); 
    } 

    #endregion 

    #region ColumnCount Property 

    /// <summary> 
    /// Adds the specified number of Columns to ColumnDefinitions. 
    /// Default Width is Auto 
    /// </summary> 
    public static readonly DependencyProperty ColumnCountProperty = 
     DependencyProperty.RegisterAttached(
      "ColumnCount", typeof(int), typeof(GridHelpers), 
      new PropertyMetadata(-1, ColumnCountChanged)); 

    // Get 
    public static int GetColumnCount(DependencyObject obj) 
    { 
     return (int)obj.GetValue(ColumnCountProperty); 
    } 

    // Set 
    public static void SetColumnCount(DependencyObject obj, int value) 
    { 
     obj.SetValue(ColumnCountProperty, value); 
    } 

    // Change Event - Add the Columns 
    public static void ColumnCountChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     if (!(obj is Grid) || (int)e.NewValue < 0) 
      return; 

     Grid grid = (Grid)obj; 
     grid.ColumnDefinitions.Clear(); 

     for (int i = 0; i < (int)e.NewValue; i++) 
      grid.ColumnDefinitions.Add(
       new ColumnDefinition() { Width = GridLength.Auto }); 

     SetStarColumns(grid); 
    } 

    #endregion 

    #region StarRows Property 

    /// <summary> 
    /// Makes the specified Row's Height equal to Star. 
    /// Can set on multiple Rows 
    /// </summary> 
    public static readonly DependencyProperty StarRowsProperty = 
     DependencyProperty.RegisterAttached(
      "StarRows", typeof(string), typeof(GridHelpers), 
      new PropertyMetadata(string.Empty, StarRowsChanged)); 

    // Get 
    public static string GetStarRows(DependencyObject obj) 
    { 
     return (string)obj.GetValue(StarRowsProperty); 
    } 

    // Set 
    public static void SetStarRows(DependencyObject obj, string value) 
    { 
     obj.SetValue(StarRowsProperty, value); 
    } 

    // Change Event - Makes specified Row's Height equal to Star 
    public static void StarRowsChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString())) 
      return; 

     SetStarRows((Grid)obj); 
    } 

    #endregion 

    #region StarColumns Property 

    /// <summary> 
    /// Makes the specified Column's Width equal to Star. 
    /// Can set on multiple Columns 
    /// </summary> 
    public static readonly DependencyProperty StarColumnsProperty = 
     DependencyProperty.RegisterAttached(
      "StarColumns", typeof(string), typeof(GridHelpers), 
      new PropertyMetadata(string.Empty, StarColumnsChanged)); 

    // Get 
    public static string GetStarColumns(DependencyObject obj) 
    { 
     return (string)obj.GetValue(StarColumnsProperty); 
    } 

    // Set 
    public static void SetStarColumns(DependencyObject obj, string value) 
    { 
     obj.SetValue(StarColumnsProperty, value); 
    } 

    // Change Event - Makes specified Column's Width equal to Star 
    public static void StarColumnsChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString())) 
      return; 

     SetStarColumns((Grid)obj); 
    } 

    #endregion 

    private static void SetStarColumns(Grid grid) 
    { 
     string[] starColumns = 
      GetStarColumns(grid).Split(','); 

     for (int i = 0; i < grid.ColumnDefinitions.Count; i++) 
     { 
      if (starColumns.Contains(i.ToString())) 
       grid.ColumnDefinitions[i].Width = 
        new GridLength(1, GridUnitType.Star); 
     } 
    } 

    private static void SetStarRows(Grid grid) 
    { 
     string[] starRows = 
      GetStarRows(grid).Split(','); 

     for (int i = 0; i < grid.RowDefinitions.Count; i++) 
     { 
      if (starRows.Contains(i.ToString())) 
       grid.RowDefinitions[i].Height = 
        new GridLength(1, GridUnitType.Star); 
     } 
    } 
} 
+1

嘗試將Rachel的解決方案與這一個結合起來:[在樣式中使用附加屬性](http://stackoverflow.com/questions/7139641/how-to-use-attached-property-within-a-style)。這導致像這樣''你有你要的東西 – 2016-02-18 22:21:57

6

我知道這是個老問題,但我想用一個不需要任何助手類的解決方案。

可以通過使用帶有網格的ItemsControl作爲其ItemsPanelTemplate來設置ColumnDefinitions。這在下面的例子中顯示。

<ItemsControl> 
    <ItemsControl.Resources> 
     <Style TargetType="ItemsControl"> 
      <Setter Property="ItemsPanel"> 
       <Setter.Value> 
        <ItemsPanelTemplate> 
         <Grid> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition /> 
           <ColumnDefinition Width="40" /> 
          </Grid.ColumnDefinitions> 
         </Grid> 
        </ItemsPanelTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ItemsControl.Resources> 
    <TextBox Text="First column" /> 
    <TextBox Text="second column" Grid.Column="1" /> 
</ItemsControl> 
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" 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>