这可能很明显......我如何在同一个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"/>
替换。
答案 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 属性相比,这种方法应该没有那么详尽。