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

标签 xaml grid row converter named

如果我命名网格中的每一行和每一列,我可以设置控件的 grid.row="Row_Top"吗?我已经定义了 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;
    }
}

然后您可以按如下方式使用这些扩展:

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

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

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

关于XAML:我可以按名称引用网格行或列吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2183159/

相关文章:

wpf - 从 DataTrigger 内部更改样式

c# - 在 XAML 中重用路径对象

Excel - 如何通过使用函数实现使用 "Ctrl+End"的等效结果

excel - 我想比较 SSIS 中两个不同 Excel 文件的行数并获取电子邮件警报

c# - 在 visual studio community 2017 中找不到类型 ObservableDictionary

c# - 将按钮放在右下角的 XAML 代码

grid - 如何在表单中使用 RecId 作为外键

html - 具有相等边距的响应式 2 列网格

javascript - 如何检查网格的特定位置是否有元素?

MySQL Select - 数字时合并行