2011-03-03 11 views
16

Quiero saber cómo puedo estilo que una cuadrícula de modo que no es necesario especificar elcómo el estilo de cuadrícula ColumnDefinitions en WPF

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

cada vez?

¡Muchas gracias!

ps: Intenté buscar primero en Google. Pero no pude encontrar ninguna respuesta. ¿Alguien que encuentre la respuesta de google podría decirme qué palabra clave usa para buscar? A veces me resulta difícil determinar qué palabra clave usar para buscar.

ps2: soy demasiado vago, cada vez que abro Chrome escribe algo y busca. Si no se encuentra nada, concluyo que no encontré nada y vengo aquí. ¿Hay alguien que busque en Google, luego no encuentre nada, luego abra bing.com y busque? ¿Y no encuentra nada e ingresa a Yahoo y busca y busca? ...

Respuesta

1

Creo que no es posible porque no puede establecer un estilo que afecte a todas las definiciones de columnas.

Grid no es compatible con ControlTemplate, por lo que no puede hacerlo con la composición.

El único truco que puedo pensar sería crear un control de usuario con esas 2 columnas y extender la grilla. Pero eso es desagradable.

7

Crear propiedad de dependencia adjunta con el cambio de devolución de llamada para sincronizar elementos de la colección:

<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> 

Implementación (apoyo RowDefinition omitidos ya que es básicamente idéntica):

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

Esto matará el rendimiento ya que no se ejecutará hasta que se complete el pase de disposición inicial. –

+0

¿Puedes ampliar eso? He realizado un seguimiento y 'OnColumnDefinitionChanged' se ejecuta antes de cualquier elemento Measure/Arrange/LayoutUpdated methods/events of Grid. Tampoco afecta la cantidad de veces que se ejecutan. –

+0

Aparece el mensaje de error: ''valor 'ya pertenece a otra' ColumnDefinitionCollection'.Así que probablemente necesite crear una copia de ColumnDefinition. –

22

Siempre fue una manía mía de Tengo que escribir RowDefinitions y ColumnDefinitions, así que un día me cansé de eso y escribí algunos attached properties que pueden usarse para este tipo de cosas.

Ahora, en lugar de escribir mi definición Grid así:

<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> 

puedo usar

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

</Grid> 

Sólo se permite la Auto y * tamaños, pero la mayoría de las veces eso es todo lo que soy utilizando.

También es compatible con enlaces para dinámicamente dimensionados Rejillas

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

Aquí hay una copia del código en caso de que el sitio nunca se cae:

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

Intente combinar la solución de Rachel con esta: [Usar propiedad adjunta en Style] (http://stackoverflow.com/questions/7139641/how-to-use-attached-property-within-a-style). Esto produce algo como esto '' y tienes lo que estás pidiendo –

6

Sé que esto es una cuestión de edad , pero me gustaría contribuir con una solución que no requiere ninguna clase de ayuda.

Es posible establecer ColumnDefinitions utilizando ItemsControl con una Grilla como ItemsPanelTemplate. Esto se muestra en el ejemplo a continuación.

<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

Aquí manera:

1) Crear una colección con una propiedad adjunta como esto:

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) A continuación, se puede usar como un recurso y en un estilo de cuadrícula como esta:

Tenga en cuenta que se debe utilizar x:Shared="False". Si no, se agregará la misma definición a muchas cuadrículas que provocan que WPF lance.

<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> 
Cuestiones relacionadas