如果我给网格中的每一行和列命名,那么我能否设置控件的grid.row="Row_Top"?我已经定义了静态资源来引用它,但是是否有转换器或其他方法可以在没有资源的情况下实现这一点?
据我所知,没有内置的方法可以完成此操作... 然而,您可以使用标记扩展来通过名称检索行或列:
[MarkupExtensionReturnType(typeof(int))]
public abstract class GridBandExtensionBase : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider != null)
{
var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target != null)
{
var obj = target.TargetObject as DependencyObject;
if (obj != null)
{
var grid = VisualTreeHelper.GetParent(obj) as Grid;
if (grid != null)
{
return GetBandIndex(grid);
}
}
}
}
return 0;
}
protected abstract int GetBandIndex(Grid grid);
}
public class GridRowExtension : GridBandExtensionBase
{
public GridRowExtension() {}
public GridRowExtension(string rowName)
{
this.RowName = rowName;
}
[ConstructorArgument("rowName")]
public string RowName { get; set; }
protected override int GetBandIndex(System.Windows.Controls.Grid grid)
{
for (int i = 0; i < grid.RowDefinitions.Count; i++)
{
if (grid.RowDefinitions[i].Name == RowName)
{
return i;
}
}
return 0;
}
}
public class GridColumnExtension : GridBandExtensionBase
{
public GridColumnExtension() {}
public GridColumnExtension(string columnName)
{
this.ColumnName = columnName;
}
[ConstructorArgument("columnName")]
public string ColumnName { get; set; }
protected override int GetBandIndex(System.Windows.Controls.Grid grid)
{
for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
{
if (grid.ColumnDefinitions[i].Name == ColumnName)
{
return i;
}
}
return 0;
}
}
你可以按照以下方式使用这些扩展:
<Button Grid.Row="{my:GridRow Row_Top}"
Grid.Column="{my:GridColumn Column_Right}"
Content="Hello world" />
注意: 如果你将这些标记扩展与应用程序放在同一个程序集中编译,设计师将无法调用带参数的构造函数(但在运行时可以正常工作)。这是一个已知的错误,Microsoft 没有意图修复它。如果你想让它在设计时正常工作,请将标记扩展放在单独的程序集中,或者显式指定 RowName/ColumnName 属性,如下:
<Button Grid.Row="{my:GridRow RowName=Row_Top}"
Grid.Column="{my:GridColumn ColumnName=Column_Right}"
Content="Hello world" />