dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.07k stars 1.17k forks source link

Alias for Grid‘s RowDefinition and ColumnDefinition #2844

Open TruePluto opened 4 years ago

TruePluto commented 4 years ago

I don't know if there is a way to make a alias for Grid‘s cell. But I want to how to implement the following feature:

    <Grid x:Name="OuterGird">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" alias="id"/>
            <ColumnDefinition Width="*" alias="name"/>
            <ColumnDefinition Width="Auto" alias="birthday"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" alias="title"/>
            <RowDefinition Height="auto" alias="Address Bar"/>
            <RowDefinition Height="auto" alias="document "/>
            <RowDefinition Height="auto" alias="status bar "/>
        </Grid.RowDefinitions>

        <Grid x:Name="InnerGrid" Grid.Column="id" Grid.Row="title"/>
        <TextBlock x:Name="Address" Grid.Column="id" Grid.Row="Address Bar"/>
        ...
    </Grid>

so when I Change the OuterGrid' columns defintion or rows difinition I don’t need to change the InnerGrid's properties of Grid.Column or Grid.Row Thank you for your attention

lindexi commented 4 years ago

Looks like a dup of #166 ?

TruePluto commented 4 years ago

Looks like a dup of #166 ?

NO the #166 just want to use a quick method to define columns and rows but when the column or rows definition changed such as

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" alias="id"/>
            <ColumnDefinition Width="*" alias="name"/>
            <ColumnDefinition Width="Auto" alias="birthday"/>
        </Grid.ColumnDefinitions>
<Grid x:Name="InnerGrid" Grid.Column="1" Grid.Row="title"/>

to

<Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" alias="id"/>
            <ColumnDefinition Width="Auto" alias="AddAnewcolumn"/>
            <ColumnDefinition Width="*" alias="name"/>
            <ColumnDefinition Width="Auto" alias="birthday"/>
        </Grid.ColumnDefinitions>
<Grid x:Name="InnerGrid" Grid.Column="2" Grid.Row="title"/>

the column of "InnerGrid" from Grid.Column="1" to Grid.Column="2" most of the elements should changed the properties. but using the aliases these modifies are unnecessary. thank you for your attention

weltkante commented 4 years ago

You can already give a name to columns/rows like you can give to any other element, so why invent a new attribute alias?

TruePluto commented 4 years ago

You can already give a name to columns/rows like you can give to any other element, so why invent a new attribute alias?

I believe you replied without reading my question. I want to know the alias could be added to the grid so the other elements can used it such as the an Attached Property like Grid.Column. then when we insert a new row or new column we needn't modify the property but use Grid.Column or Grid.Row will need to changed the property

weltkante commented 4 years ago

I believe you replied without understanding my response. I said there's already a way to name rows/columns, via 'Name' property, so why does it need to have two names?

In other words, why should I have to type <GridColumn Width="auto" Name="age" Alias="age" /> if I need to make use of both functionalities?

lindexi commented 4 years ago

@weltkante Do you mean that: we can use the Name property to set to the Column? Just like the code

       <Grid.RowDefinitions>
        <RowDefinition Height="auto" Name="Title"/>
        <RowDefinition Height="auto" Name="AddressBar"/>
      </Grid.RowDefinitions>

    <Grid x:Name="InnerGrid"  Grid.Row="Title"/>
    <TextBlock x:Name="Address"  Grid.Row="AddressBar"/>

I very much agree with this view

TruePluto commented 4 years ago

@weltkante Do you mean that: we can use the Name property to set to the Column? Just like the code

       <Grid.RowDefinitions>
        <RowDefinition Height="auto" Name="Title"/>
        <RowDefinition Height="auto" Name="AddressBar"/>
      </Grid.RowDefinitions>

    <Grid x:Name="InnerGrid"  Grid.Row="Title"/>
    <TextBlock x:Name="Address"  Grid.Row="AddressBar"/>

I very much agree with this view

hahahaha , I don't know how to express my idea. but thank lindexi . yes that my mean sorry for my poor english thank you all

lindexi commented 3 years ago

@TruePluto How about this code:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition local:GridExtensions.Name="R0" />
      <RowDefinition local:GridExtensions.Name="R1" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
      <ColumnDefinition local:GridExtensions.Name="C1" />
    </Grid.ColumnDefinitions>
    <TextBlock local:GridExtensions.RowName="R1" local:GridExtensions.ColumnName="C1" Text="12" />
  </Grid>

The GridExtensions is:

    public class GridExtensions
    {
        public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached(
            "Name", typeof(string), typeof(GridExtensions), new PropertyMetadata(default(string)));

        public static void SetName(DependencyObject element, string value)
        {
            element.SetValue(NameProperty, value);
        }

        public static string GetName(DependencyObject element)
        {
            return (string) element.GetValue(NameProperty);
        }

        public static readonly DependencyProperty RowNameProperty = DependencyProperty.RegisterAttached(
            "RowName", typeof(string), typeof(GridExtensions),
            new PropertyMetadata(default(string), RowName_PropertyChanged));

        private static void RowName_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is FrameworkElement frameworkElement)
            {
                if (e.NewValue is string rowName)
                {
                    if (string.IsNullOrEmpty(rowName))
                    {
                        return;
                    }

                    if (frameworkElement.Parent is Grid grid)
                    {
                        for (var i = 0; i < grid.RowDefinitions.Count; i++)
                        {
                            var gridRowDefinition = grid.RowDefinitions[i];
                            var gridRowName = GetName(gridRowDefinition);
                            if (!string.IsNullOrEmpty(gridRowName) &&
                                gridRowName.Equals(rowName, StringComparison.Ordinal))
                            {
                                Grid.SetRow(frameworkElement, i);
                                return;
                            }
                        }
                    }
                    else
                    {
                        throw new ArgumentException("xxxxxxxxxxxxxx");
                    }
                }
            }
        }

        public static void SetRowName(DependencyObject element, string value)
        {
            element.SetValue(RowNameProperty, value);
        }

        public static string GetRowName(DependencyObject element)
        {
            return (string) element.GetValue(RowNameProperty);
        }

        public static readonly DependencyProperty ColumnNameProperty = DependencyProperty.RegisterAttached(
            "ColumnName", typeof(string), typeof(GridExtensions),
            new PropertyMetadata(default(string), ColumnName_PropertyChanged));

        private static void ColumnName_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is FrameworkElement frameworkElement)
            {
                if (e.NewValue is string columnName)
                {
                    if (string.IsNullOrEmpty(columnName))
                    {
                        return;
                    }

                    if (frameworkElement.Parent is Grid grid)
                    {
                        for (var i = 0; i < grid.ColumnDefinitions.Count; i++)
                        {
                            var gridColumnDefinition = grid.ColumnDefinitions[i];
                            var gridColumnName = GetName(gridColumnDefinition);
                            if (!string.IsNullOrEmpty(gridColumnName) &&
                                gridColumnName.Equals(columnName, StringComparison.Ordinal))
                            {
                                Grid.SetColumn(frameworkElement, i);
                                return;
                            }
                        }
                    }
                    else
                    {
                        throw new ArgumentException("xxxxxxxxxxxxxxxxx");
                    }
                }
            }
        }

        public static void SetColumnName(DependencyObject element, string value)
        {
            element.SetValue(ColumnNameProperty, value);
        }

        public static string GetColumnName(DependencyObject element)
        {
            return (string) element.GetValue(ColumnNameProperty);
        }
    }

See https://github.com/lindexi/lindexi_gd/tree/00e0d126/JurgekebowhawiNofeerileji

lindexi commented 2 years ago

I brought it to HandyControl

miloush commented 2 years ago

This probably needs to take into account when row/column collections and their names are manipulated at runtime.

Another way to do this currently might be through a markup extension.