XAML:我可以按名称引用网格行或列吗?

XAML:我可以按名称引用网格行或列吗?,xaml,grid,row,converter,named,Xaml,Grid,Row,Converter,Named,如果我给网格中的每一行和每一列命名,我可以设置控件的网格吗?我已经定义了StaticResources来引用它,但是没有这个资源,有没有一个转换器或者其他方法来完成这个任务呢?据我所知,没有内置的方法来完成它。。。但是,您可以使用标记扩展按名称检索行或列: [MarkupExtensionReturnType(typeof(int))] public abstract class GridBandExtensionBase : MarkupExtension { public overr

如果我给网格中的每一行和每一列命名,我可以设置控件的网格吗?我已经定义了StaticResources来引用它,但是没有这个资源,有没有一个转换器或者其他方法来完成这个任务呢?

据我所知,没有内置的方法来完成它。。。但是,您可以使用标记扩展按名称检索行或列:

[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;
    }
}
[MarkupExtensionReturnType(typeof(int))]
公共抽象类GridBandExtensionBase:MarkupExtension
{
公共覆盖对象ProviderValue(IServiceProvider服务提供程序)
{
if(serviceProvider!=null)
{
var target=serviceProvider.GetService(typeof(IProvideValueTarget))作为IProvideValueTarget;
如果(目标!=null)
{
var obj=target.TargetObject作为DependencyObject;
如果(obj!=null)
{
var grid=visualtreeheloper.GetParent(obj)作为网格;
如果(网格!=null)
{
返回GetBandIndex(网格);
}
}
}
}
返回0;
}
受保护的抽象int GetBandIndex(网格);
}
公共类GridRowExtension:GridBandExtensionBase
{
公共GridRowExtension(){}
公共GridRowExtension(字符串rowName)
{
this.RowName=RowName;
}
[构造器参数(“行名称”)]
公共字符串行名{get;set;}
受保护的覆盖int GetBandIndex(System.Windows.Controls.Grid)
{
对于(int i=0;i
然后,您可以按如下方式使用这些扩展:

<Button Grid.Row="{my:GridRow Row_Top}"
        Grid.Column="{my:GridColumn Column_Right}"
        Content="Hello world" />
<Button Grid.Row="{my:GridRow RowName=Row_Top}"
        Grid.Column="{my:GridColumn ColumnName=Column_Right}"
        Content="Hello world" />

注意:如果在与应用程序相同的程序集中编译这些标记扩展,则设计器将无法使用参数调用构造函数(但在运行时可以正常工作)。这是微软不打算解决的问题。如果希望它在设计时工作,请将标记扩展放在单独的程序集中,或显式指定RowName/ColumnName属性,如下所示:

<Button Grid.Row="{my:GridRow Row_Top}"
        Grid.Column="{my:GridColumn Column_Right}"
        Content="Hello world" />
<Button Grid.Row="{my:GridRow RowName=Row_Top}"
        Grid.Column="{my:GridColumn ColumnName=Column_Right}"
        Content="Hello world" />

谢谢托马斯,回答得很好!