从 Grid.Row\Column DependencyProperty 中提取索引

Extracting index from 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>

和以下多值转换器:

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();
    }
}

如何从命令中的 DependencyProperty 获取 Grid.Row\Column 的实际值?:

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;

您应该在 Visual Studio 的输出 Window 中看到绑定错误消息,因为 Button 不是此处的祖先元素。

您应该使用 Self 而不是 FindAncestor 来使用 Button 作为源对象:

<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;
        ...
    }
}