XAML: Могу ли я обратиться к строке или столбцу таблицы по имени? - PullRequest
2 голосов
/ 02 февраля 2010

Если я назову каждую строку и столбец в сетке, могу ли я установить grid.row = "Row_Top" элемента управления? Я определил StaticResources, чтобы сослаться на него, но есть ли конвертер или какой-либо другой метод для выполнения этого без ресурса?

1 Ответ

8 голосов
/ 02 февраля 2010

Насколько я знаю, нет встроенного способа сделать это ... однако вы можете использовать расширения разметки для извлечения строки или столбца по его имени:

[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" />
...