2011-03-03 70 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>