如何在Grid.Row / Grid.Column中引用行/列定义?

时间:2011-06-22 23:35:36

标签: wpf xaml reference

这可能很明显......我如何在同一个XAML文件中引用XAML元素?

示例:

<Grid.RowDefinitions>
    <RowDefinition Height="661*" Name="someGridRow" />
    <RowDefinition Height="230*" Name="someOtherGridRow"/>
</Grid.RowDefinitions>

然后我在网格中定义了各种控件,我想按名称引用这些行,而不是按数字引用:

<RichTextBox Grid.Row="someGridRow" ... />

因为如果我在许多控件上使用Grid.Row="0",那么当我在第一行之前添加一行时,我必须手动更改所有对Grid.Row="1"的引用。

感谢。

修改

感谢答案,我一直在阅读XAML。

毕竟,显然可以通过名称引用前一个元素:

Grid.Row="{Binding ElementName=someGridRow}"

Grid.Row="{x:Reference someGridRow}"

但这并不能完全解决问题,因为Grid.Row需要一个int,而someGridRow不是int,它是一个System.Windows.Controls.RowDefinition。

所需要的是XAML等效于

Grid.Row = grid.RowDefinitions.IndexOf(someGridRow)

后面的代码将被写入

Grid.SetRow(richTextBox, grid.RowDefinitions.IndexOf(someGridRow))

或对Grid.Row绑定到对象grid上的属性,该对象的路径为"RowDefinitions.IndexOf",参数为someGridRow

PropertyPath path = new PropertyPath("RowDefinitions.IndexOf", someGridRow);
Binding binding = new Binding() { ElementName = "grid", Path = path };
richTextBox.SetBinding(Grid.RowProperty, binding);

(这实际上在C#中不起作用,所以我必须做错事,尽管上面的Grid.SetRow确实有效)

XAML 2009定义<x:Arguments>来调用具有参数的构造函数。如果在WPF XAML中有效,那么我想这样的东西会起作用吗?

<Grid.Row>
  <Binding ElementName="grid">
    <Binding.Path>
      <PropertyPath>
        <x:Arguments>
          RowDefinitions.IndexOf
          <Binding ElementName="someGridRow"/>
        </x:Arguments>
      </PropertyPath>
    </Binding.Path>
  </Binding>
</Grid.Row>

其中<Binding ElementName="someGridRow"/>也可以在XAML 2009中由<x:Reference Name="someGridRow"/>替换。

3 个答案:

答案 0 :(得分:15)

对于lulz:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Controls;
using System.Windows;

namespace Test.MarkupExtensions
{
    class GridDefinitionExtension : MarkupExtension
    {
        public string Name { get; set; }

        public GridDefinitionExtension(string name)
        {
            Name = name;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var refExt = new Reference(Name);
            var definition = refExt.ProvideValue(serviceProvider);
            if (definition is DefinitionBase)
            {
                var grid = (definition as FrameworkContentElement).Parent as Grid;
                if (definition is RowDefinition)
                {
                    return grid.RowDefinitions.IndexOf(definition as RowDefinition);
                }
                else
                {
                    return grid.ColumnDefinitions.IndexOf(definition as ColumnDefinition);
                }
            }
            else
            {
                throw new Exception("Found object is neither a RowDefinition nor a ColumnDefinition");
            }
        }
    }
}
<Grid Width="200" Height="200"
      xmlns:me="clr-namespace:Test.MarkupExtensions">
    <Grid.RowDefinitions>
        <RowDefinition Name="row1" />
        <RowDefinition Name="row2" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Name="col1" />
        <ColumnDefinition Name="col2" />
    </Grid.ColumnDefinitions>
    <Border Background="Lime" Grid.Row="{me:GridDefinition row1}" Grid.Column="{me:GridDefinition col1}" />
    <Border Background="Red" Grid.Row="{me:GridDefinition row2}" Grid.Column="{me:GridDefinition col1}" />
    <Border Background="Yellow" Grid.Row="{me:GridDefinition row1}" Grid.Column="{me:GridDefinition col2}" />
    <Border Background="Blue" Grid.Row="{me:GridDefinition row2}" Grid.Column="{me:GridDefinition col2}" />
</Grid>

答案 1 :(得分:2)

遗憾的是,这不起作用。

所讨论的附加属性(即:Grid.Row)由网格用来处理它们自己的布局,以及它的设计方式,你必须输入数字。

不幸的是,在插入行时更改数字在XAML开发中非常常见。一个选项 - 如果您知道要添加行,可以放入未使用的额外“零高度”行,稍后再使用它们。

答案 2 :(得分:0)

另一种获取 Grid.Column 的方法是像这样绑定到 ViewModel:

<TextBlock Text="Nummer: " Grid.Column="{Binding Cols.C1}" />

在视图模型中:

public ColumnDefs Cols { get; }

最后是 ColumnWidth 值的定义:

public class ColumnDefs
{
    public int C1 => 0; // or however you retrieve the columns index
    public int C2 => 1;
}

知道,如果您必须插入列(也适用于行),您只需更改 ViewModel 中的索引值。与更改 xaml 中的每个 Grid.Column 属性相比,这种方法应该没有那么详尽。