Подтвердить что ты не робот

Как стиль Grid ColumnDefinitions в WPF

Я хочу знать, как я могу создать сетку, так что мне не нужно указывать

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

каждый раз?

Большое спасибо!

ps: Сначала я попытался выполнить поиск в Google. Но я не мог найти ответа. Любой, кто найдет ответ из Google, мог бы рассказать мне, какое ключевое слово вы используете для поиска? Иногда мне трудно определить, какое ключевое слово использовать для поиска.

ps2: Я слишком ленив, каждый я просто открываю хром и набираю что-то и ищу. Если ничего не найдено, я не могу найти ничего и прийти сюда. Кто-нибудь будет искать в Google, а затем ничего не найти, а затем открыть bing.com и выполнить поиск? И ничего не найти и пойти на yahoo и искать и искать?.....

4b9b3361

Ответ 1

Мне всегда нравилось писать "RowDefinitions и ColumnDefinitions", поэтому однажды я устал от этого и написал прикрепленные свойства, которые можно использовать для такого рода вещей.

Теперь вместо написания определения 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 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 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 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 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);
        }
    }
}

Ответ 2

Создать связанное свойство зависимостей с обратным вызовом изменения для синхронизации элементов коллекции:

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

Реализация (поддержка RowDefinition опущена, поскольку она в основном идентична):

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

Ответ 3

Я знаю, что это старый вопрос, но я хотел бы внести вклад в решение, которое не требует какого-либо вспомогательного класса.

Можно установить ColumnDefinitions с помощью элемента ItemsControl с сеткой в ​​качестве элемента ItemsPanelTemplate. Это показано в следующем примере.

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

Ответ 4

Я считаю, что это невозможно, потому что вы не можете установить стиль, который влияет на все ColumnDefinition (s).

Сетка не поддерживает ControlTemplate, поэтому вы не можете делать это с композицией.

Единственный хак, о котором я могу думать, - создать пользовательский элемент управления с этими двумя столбцами и расширить сетку. Но это противно.

Ответ 5

Вот способ:

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>