Wpf 如何在Grid.row/Grid.column中引用行/列定义?
这可能是显而易见的。。。以后如何在同一个XAML文件中引用XAML元素 例如: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需要
<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;
}