Wpf 如何在Grid.row/Grid.column中引用行/列定义?

Wpf 如何在Grid.row/Grid.column中引用行/列定义?,wpf,xaml,reference,Wpf,Xaml,Reference,这可能是显而易见的。。。以后如何在同一个XAML文件中引用XAML元素 例如: <Grid.RowDefinitions> <RowDefinition Height="661*" Name="someGridRow" /> <RowDefinition Height="230*" Name="someOtherGridRow"/> </Grid.RowDefinitions> 或 但这并不能完全解决问题,因为Grid.Row需要

这可能是显而易见的。。。以后如何在同一个XAML文件中引用XAML元素

例如:

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

但这并不能完全解决问题,因为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
确实起作用)

XAML2009定义了
来调用具有参数的构造函数。如果这在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>

RowDefinitions.IndexOf

在XAML2009中,
也可以替换为

不幸的是,这不起作用

Grid使用所讨论的附加属性(即:Grid.Row)来处理它们自己的布局,按照其设计方式,您必须输入数字

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

对于lulz:

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Markup;
使用System.Windows.Controls;
使用System.Windows;
namespace Test.MarkupExtensions
{
类GridDefinitionExtension:MarkupExtension
{
公共字符串名称{get;set;}
公共GridDefinitionExtension(字符串名称)
{
名称=名称;
}
公共覆盖对象ProviderValue(IServiceProvider服务提供程序)
{
var refExt=新引用(名称);
变量定义=refExt.ProvideValue(serviceProvider);
if(定义为定义基础)
{
var grid=(定义为FrameworkContentElement)。父级为grid;
if(定义为行定义)
{
返回grid.RowDefinitions.IndexOf(定义为RowDefinition);
}
其他的
{
返回grid.ColumnDefinitions.IndexOf(定义为ColumnDefinition);
}
}
其他的
{
抛出新异常(“找到的对象既不是行定义也不是列定义”);
}
}
}
}

获取网格的另一种方法。列将绑定到ViewModel,如下所示:

<TextBlock Text="Nummer: " Grid.Column="{Binding Cols.C1}" />
最后是ColumnWidth值的定义:

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

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

谢谢。为什么这么简单的事情不可能?类似于
Grid.Row=“{x:Name someGridRow}”
的东西应该被实现…@SemMike:我怀疑这是因为它是如何工作的。Grid为Grid.Row调查它的子项,并且不涉及真正的绑定。。。任何命名都必须使用非类型安全标识符,这可能会导致奇怪的问题。使用
Name=“someName”
您已经可以在代码隐藏中引用该项,那么为什么不在XAML本身中呢?XAML中的“类型安全性”不低于C#。。。无论如何这是不可能的,所以这一点是没有意义的,谢谢你让我很快摆脱了痛苦!对不起,我必须让另一个人的答案被接受!不过,香草XAML是不可能的(令人惊讶),所以你是对的。@SemMike:是的,没问题。他的标记扩展是解决这个问题的一个很好的方法。通过标记扩展解决这个问题的好方法。非常感谢!我根本不知道标记扩展或类型转换器,我现在正在MSDN上阅读它们。我想我真的会用这种东西(不仅仅是“为了休息”),它已经让我更喜欢XAML了…@SemMike:我想我应该提到,这可能会对更大的网格产生一些性能影响,因为
引用
查找行为相当复杂,并且行数是通过
索引
检索的,这取决于实现速度。这就是为什么我的答案前面会加上那一行。@SemMike:刚才看了一下,根据反编译器
IndexOf
应该有O(1),我想在这里可能不应该过早地考虑优化。谢谢,我可能最终会使用你的方法,但我现在对XAML很好奇,我阅读并编辑了原始问题……我认为所有这些都不会起作用,因为属性路径不允许调用像
IndexOf
这样的方法。
<Grid.Row>
  <Binding ElementName="grid">
    <Binding.Path>
      <PropertyPath>
        <x:Arguments>
          RowDefinitions.IndexOf
          <Binding ElementName="someGridRow"/>
        </x:Arguments>
      </PropertyPath>
    </Binding.Path>
  </Binding>
</Grid.Row>
<TextBlock Text="Nummer: " Grid.Column="{Binding Cols.C1}" />
public ColumnDefs Cols { get; }

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