如何从Convert中获取ConvertBack参数?

How to get in ConvertBack parameters from Convert?

问题:

我正在使用 MultiBinding 和转换器将 (x,y) 坐标传递给方法。

而且我不能让它反向工作:

public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var x = (int)values[0];
        var y = (int)values[1];
        return Model.Get(x, y);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        Model.Set(x, y, value); // how to get x, y here?
        return new object[] { Binding.DoNothing, Binding.DoNothing };
    }
}

附加信息:

数据将以table的形式可视化。这是单元格模板:

<TextBox>
    <TextBox.Text>
        <MultiBinding Converter="{StaticResource converter}" Mode="TwoWay">
            <Binding Path="X" Mode="OneWay" />
            <Binding Path="Y" Mode="OneWay" RelativeSource="..." />
        </MultiBinding>
    </TextBox.Text>
</TextBox>

想法是使用转换器,它接收 x(来自单元格视图模型)和 y(来自父列视图模型,注意 RelativeSource)并调用 Get(x,y) 显示值。

但是,当用户输入内容时,ConvertBack 被调用,我需要调用 Set(x, y, value) 方法。

如何将 xy 传递给 ConvertBack

简短的回答是您不能直接在您的ConvertBack方法中获取xy的值。将IMultiValueConverterConvert多个值合并为一个值。因此,ConvertBack 方法将执行相反的操作:将单个值转换为多个值。

这完全取决于您的 Model.Get(x, y) 方法 return。它需要 return 一个足够独特的值,以便您从中获取 xy 的单独值。

示例:为每对 (x,y) 创建唯一的字符串。

可能会有或多或少的变通方法来让这样的多值转换器工作。但我建议您将多值转换器保持单向,但 return 一个包装实际文本的容器对象 属性.

不是直接绑定到 TextBox.Text 属性,而是绑定到其他 属性(例如 DataContextTag),然后再绑定文本到容器值。

小例子:

<TextBox Text="{Binding Value}">
    <TextBox.DataContext>
        <MultiBinding Converter="{StaticResource cMyConverter}">
            <Binding Path="X"/>
            <Binding Path="Y"/>
        </MultiBinding>
    </TextBox.DataContext>
</TextBox>

有容器和转换器:

public class ValueProxy
{
    public int X { get; set; }
    public int Y { get; set; }

    public string Value
    {
        get { return Model.Get(X, Y); }
        set { Model.Set(X, Y, value); }
    }
}
public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var x = (int)values[0];
        var y = (int)values[1];
        return new ValueProxy { X = x, Y = y };
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return new object[] { Binding.DoNothing, Binding.DoNothing };
    }
}

似乎很难将参数传递给ConvertBack。这可能是可能的,但有一个解决方法,使 ConvertBack 变得不必要。感谢@XAMlMAX 的想法。

实现它的一种可能性(可能有更好的方法)是使用数据模板。我们可以将 ContentControl.Content 与某些视图模型绑定,而不是将 TextBlock.Textstring 进行多重绑定,而该视图模型应该完成其余的工作,包括 Set(x, y, value) 调用。

代码如下:

public class ViewModel
{
    public int X { get; set; }
    public int Y { get; set; }

    string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            // this should be only called by the view
            _text = value;
            Model.Set(X, Y, value);
        }
    }

    public ViewModel(string text)
    {
        _text = text;
    }
}

public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var x = (int)values[0];
        var y = (int)values[1];
        return new ViewModel(Model.Get(x, y)) { X = x, Y = y };
    }

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

并且 xaml 将变为

<ContentControl Focusable="False">
    <ContentControl.Content>
        <MultiBinding Converter="{StaticResource converter}">
            <Binding Path="X" />
            <Binding Path="Y" RelativeSource="..."/>
        </MultiBinding>
    </ContentControl.Content>
</ContentControl>

数据模板在哪里

<DataTemplate DataType="{x:Type local:ViewModel}">
    <TextBox Text="{Binding Text}" />
</DataTemplate>