Извлечение индекса из Grid.Row\Column DependencyProperty

У меня есть следующая кнопка:

<Button Grid.Row="0" Grid.Column="0" Command="{Binding DrawXO}">
            <Button.CommandParameter>
                <MultiBinding Converter="{StaticResource BoardIndexConverter}">
                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}" Path="(Grid.Row)"></Binding>
                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}" Path="(Grid.Column)" ></Binding>
                </MultiBinding>
            </Button.CommandParameter>
        </Button>

и следующий MultiValueConverter:

class BoardIndexConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.Clone();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Как я могу получить фактическое значение Grid.Row\Column из DependencyProperty в моей команде?:

class DrawXOCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        var values = (object[])parameter;
        var row = (int)(values[0]);
        var column = (int)values[1];
    }

    public event EventHandler CanExecuteChanged;

1 ответ

Решение

Вы должны были видеть сообщения об ошибках привязки в окне вывода в Visual Studio, поскольку кнопка здесь не является элементом-предком.

Вместо FindAncestor ты должен использовать Self использовать кнопку в качестве исходного объекта:

<MultiBinding Converter="{StaticResource BoardIndexConverter}">
    <Binding RelativeSource="{RelativeSource Self}" Path="(Grid.Row)"/>
    <Binding RelativeSource="{RelativeSource Self}" Path="(Grid.Column)"/>
</MultiBinding>

Ваш конвертер также может быть реализован немного безопаснее:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    if (values.Length == 2 && values[0] is int && values[1] is int)
    {
        return new Tuple<int, int>((int)values[0], (int)values[1]);
    }

    return null;
}

Затем проверьте параметр команды следующим образом:

public void Execute(object parameter)
{
    var cell = parameter as Tuple<int, int>;

    if (cell != null)
    {
        var row = cell.Item1;
        var column = cell.Item2;
        ...
    }
}
Другие вопросы по тегам