6

I'm organizing my grid with RowDefinitions and ColumnDefinition, but forever when I want add a new RowDefinition in before actual any RowDefinition, I need reorganize Grid.Row of all controls

I saw RowDefinition and ColumnDefinition has a Name property, so I think is possible define Grid.Row with RowDefinition name or not? If is possible, How do

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Name="RowDictTitle" Height="27"/>
        <RowDefinition Name="RowSearchWord" Height="27"/>
        <RowDefinition/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*"/>
        <ColumnDefinition Width="2*"/>
    </Grid.ColumnDefinitions>

    <!--Row 1-->
    <TextBlock Text="Word:" VerticalAlignment="Center" Margin="10,0,0,0" Grid.Row="1"/>
    <TextBox Name="Search" Grid.ColumnSpan="2" Margin="50,2,10,2"/>

    <!--Row 2-->
    <ListBox Name="Words" Grid.Row="2" Margin="10"/>
</Grid>

I want make below

<TextBlock Text="Word" Grid.Row="RowSearchWord"/>
4

3 回答 3

7

免责声明:这个答案是一种在此元帖子所暗示的限制范围内的自我广告。它宣传了一个免费的开源项目,我(在撰写本文时)并没有从中赚钱。唯一的收获是,如果它有助于这个 SO 问题的一些未来访问者,我编写所描述的控件的时间不会被浪费。

我有完全相同的想法。这就是为什么不久前,我编写了一个使用命名列和行的自定义网格类。

我在 MIT 许可下将它放在 Codeplex 上:基于名称的网格项目

使用该控件,您可以重写 Xaml 源代码,如下所示:

<nbg:NameBasedGrid>
    <nbg:NameBasedGrid.RowDefinitions>
        <nbg:ColumnOrRow Name="RowDictTitle" Height="27"/>
        <nbg:ColumnOrRow Name="RowSearchWord" Height="27"/>
        <nbg:ColumnOrRow Name="List"/>
        <nbg:ColumnOrRow Height="50"/>
    </nbg:NameBasedGrid.RowDefinitions>
    <nbg:NameBasedGrid.ColumnDefinitions>
        <nbg:ColumnOrRow Width="1*" Name="Left"/>
        <nbg:ColumnOrRow Width="2*" Name="Right"/>
    </nbg:NameBasedGrid.ColumnDefinitions>

    <!--Row 1-->
    <TextBlock Text="Word:&quot; VerticalAlignment="Center" Margin="10,0,0,0" nbg:NameBasedGrid.Column="Left" nbg:NameBasedGrid.Row="RowSearchWord"/>
    <TextBox Name="Search" nbg:NameBasedGrid.Column="Left" nbg:NameBasedGrid.Row="RowDictTitle" nbg:NameBasedGrid.ExtendToColumn="Right" Margin="50,2,10,2"/>

    <!--Row 2-->
    <ListBox Name="Words" nbg:NameBasedGrid.Column="Left" nbg:NameBasedGrid.Row="List" Margin="10"/>
</nbg:NameBasedGrid>

优点:您将能够按名称引用列和行(包括列和行跨度!) - 不再计算列或行,当布局更改时不再更新列或行跨度。

缺点:您需要显式声明所有列和行的名称,因为NameBasedGrid.

于 2015-08-08T17:15:40.043 回答
1

好主意,但由于 Grid.Row 附加属性是一个整数,这是不可能的。

请参阅http://msdn.microsoft.com/en-us/library/system.windows.controls.grid.row.aspx

但是,可以创建一个帮助器来获取网格行的名称,找到行对象并返回其行索引。

于 2013-08-31T04:18:31.017 回答
0

我一直在寻找同样的东西。找不到我正在寻找的确切内容,因此我使用附加属性提出了自己的解决方案。

我创建了一个带有 RowName 和 ColumnName 附加属性的专用网格。(在这个例子中,我只实现了 RowName)

using System.Windows;
using System.Windows.Controls;

namespace GridNamedRows.CustomControl
{
    public class MyGrid: Grid
    {
        public static readonly DependencyProperty RowNameProperty =
                DependencyProperty.RegisterAttached(
                      "RowName",
                      typeof(string),
                      typeof(MyGrid),
                      new FrameworkPropertyMetadata(
                              "",
                              FrameworkPropertyMetadataOptions.AffectsParentArrange,
                              new PropertyChangedCallback(RowNameChanged)),
                      new ValidateValueCallback(IsStringNotNull));

        private static bool IsStringNotNull(object value)
        {
            return (value as string) != null;
        }

        private static void RowNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == null) 
            { 
                return; 
            }
            if (!(d is UIElement)) return;
            Grid parent = ((FrameworkElement)d).Parent as Grid;
            if (parent == null) return;
            //Find rowname
            for (int i = 0; i < parent.RowDefinitions.Count; i++)
            {
                if (parent.RowDefinitions[i].Name == e.NewValue.ToString())
                {
                    Grid.SetRow((UIElement)d, i);
                    break;
                }
            }
        }

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

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

它可以像这样在xaml中使用。

<Window xmlns:CustomControl="clr-namespace:GridNamedRows.CustomControl"  x:Class="GridNamedRows.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <CustomControl:MyGrid>
        <Grid.RowDefinitions>
            <RowDefinition Name="firstRow"/>
            <RowDefinition Name="secondRow"/>
            <RowDefinition Name="thirdRow"/>
        </Grid.RowDefinitions>
        <TextBox Text="one" CustomControl:MyGrid.RowName="secondRow"/>
        <TextBox Text="two" Grid.Row="2"/>
        <TextBox Text="three" CustomControl:MyGrid.RowName="firstRow"/>
    </CustomControl:MyGrid>
</Window>

它在设计器中无法正确显示,但在运行时有效。

于 2016-05-13T13:34:35.157 回答