Reputation: 21998
I am using MultiBinding
with converter to pass (x,y)
coordinates into method.
And I can't make it working in back direction:
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 };
}
}
The data will be visualized in a form of table. Here is cell template:
<TextBox>
<TextBox.Text>
<MultiBinding Converter="{StaticResource converter}" Mode="TwoWay">
<Binding Path="X" Mode="OneWay" />
<Binding Path="Y" Mode="OneWay" RelativeSource="..." />
</MultiBinding>
</TextBox.Text>
</TextBox>
The idea is to use converter, which receive x
(from cell view model) and y
(from parent column view model, notice RelativeSource
) and calls Get(x,y)
to display value.
However, when user entered something, ConvertBack
is called and I need to call Set(x, y, value)
method.
How do I pass x
and y
into ConvertBack
?
Upvotes: 3
Views: 4251
Reputation: 21998
It seems hard to pass parameters into ConvertBack
. It might be possible, but there is a workaround, which makes ConvertBack
unnecessary. Thanks to @XAMlMAX for an idea.
One possibility to achieve it (there could be a better way) is to use data templates. Instead of multi-binding TextBlock.Text
with string
we can bind ContentControl.Content
with some viewmodel, and this viewmodel should do the rest, including Set(x, y, value)
call.
Here is code:
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();
}
}
and the xaml will become
<ContentControl Focusable="False">
<ContentControl.Content>
<MultiBinding Converter="{StaticResource converter}">
<Binding Path="X" />
<Binding Path="Y" RelativeSource="..."/>
</MultiBinding>
</ContentControl.Content>
</ContentControl>
where data template is
<DataTemplate DataType="{x:Type local:ViewModel}">
<TextBox Text="{Binding Text}" />
</DataTemplate>
Upvotes: 0
Reputation: 13458
There might be more-or-less dirty workarounds to get such a multivalue converter working. But I'd suggest you keep your multivalue converter one-way, but return a container object that wraps the actual text property.
Instead of directly binding to the TextBox.Text
property, bind to some other property (eg. DataContext
or Tag
) and then bind the text to the container value.
Small example:
<TextBox Text="{Binding Value}">
<TextBox.DataContext>
<MultiBinding Converter="{StaticResource cMyConverter}">
<Binding Path="X"/>
<Binding Path="Y"/>
</MultiBinding>
</TextBox.DataContext>
</TextBox>
With container and converter:
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 };
}
}
Upvotes: 6
Reputation: 703
The short answer is that you can't directly get the values of x
and y
inside your ConvertBack
method. The IMultiValueConverter
Convert
multiple values into a single value. So, the ConvertBack
method will do the opposite: convert a single value into multiple values.
It all depends on what your Model.Get(x, y) method returns. It needs to return a value that is unique enough for you to get the separate values of x
and y
from it.
Example: create unique strings for each pair of (x,y).
Upvotes: 0