Get the Source value in the ConvertBack () method for implementing IValueConverter in a WPF binding

I am binding a dependency property to textboxex in WPF. The property is a string that has some values ​​separated by the "/" character (example: "1/2/3/4"). I need to associate individual values ​​with separate text fields, which is consistent with the following implementation of the Convert() method:

 public object Convert(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture) { if (!string.IsNullOrEmpty(value as string)) { String[] data = (value as string).Split('/'); return data[Int16.Parse(parameter as string)]; } return String.Empty; } 

And I use ConverterParameter in xaml to indicate the position of the desired value. However, the problem is with the ConvertBack() method. I don’t know how to get the original value, so that I can just add or change only one value per line (at the specified position).

Thanks for any help.

+7
source share
5 answers

In most cases, you can safely make a ConvertBack just throw a NotImplementedException .

Indeed, you simply do not have enough information to recreate the original value for your part!

If you really need the inverse transform (for example, if you use two-way binding), I would decompose the property into 3 lines in the view model (the class used in the DataContext ), and bind them separately.

+5
source

Update

You probably solved your problem already with the help of Vlad, I just thought that I should add another way to get the original value in the converter.

First you can make your converter from DependencyObject so that you can add a dependency property to it, which we will associate with

 public class MyConverter : DependencyObject, IValueConverter { public static DependencyProperty SourceValueProperty = DependencyProperty.Register("SourceValue", typeof(string), typeof(MyConverter)); public string SourceValue { get { return (string)GetValue(SourceValueProperty); } set { SetValue(SourceValueProperty, value); } } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { //... } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { object targetValue = value; object sourceValue = SourceValue; //... } } 

Unfortunately, the converter does not have a DataContext , so the binding will not work out of the box, but you can use Josh Smith perfectly DataContextSpy : Artifical inheritance contexts in WPF

 <TextBox> <TextBox.Resources> <src:DataContextSpy x:Key="dataContextSpy" /> </TextBox.Resources> <TextBox.Text> <Binding Path="YourProperty" ConverterParameter="1"> <Binding.Converter> <src:MyConverter SourceValue="{Binding Source={StaticResource dataContextSpy}, Path=DataContext.YourProperty}"/> </Binding.Converter> </Binding> </TextBox.Text> </TextBox> 

End of update

Dr.WPF has an elegant solution for this, see the following chain
How to access binding source in ConvertBack ()?

Edit

Using the Dr.WPF solution, you can specify both the line index and the TextBox source to converter using this (possibly a little detailed) code example

 <TextBox dw:ObjectReference.Declaration="{dw:ObjectReference textBoxSource}"> <TextBox.Text> <Binding Path="YourStringProperty" Converter="{StaticResource YourConverter}"> <Binding.ConverterParameter> <x:Array Type="sys:Object"> <sys:Int16>1</sys:Int16> <dw:ObjectReference Key="textBoxSource"/> </x:Array> </Binding.ConverterParameter> </Binding> </TextBox.Text> </TextBox> 

And then you can later access both the index and the TextBox in the ConvertBack method

 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { object[] parameters = parameter as object[]; short index = (short)parameters[0]; object source = (parameters[1] as TextBox).DataContext; //... } 
+13
source

Could you use IMultiValueConverter and MultiBinding?

 public interface IMultiValueConverter { object Convert(object[] values, Type targetType, object parameter, CultureInfo culture); object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture); } 
+1
source

In this case, if you really want to edit the components, you can imagine your number as a more complex object, which allows you to access your 4 components using an indexer. So this is just a simple binding, and an object that supports 4 parts gets access and can combine the whole number:

 public class MyNumber { public int this[int index] { get { /**/ } set { /**/ } } public string FullNumber { get { /**/ } } } <TextBox Text={Binding MyNumber[0]}" /> 
+1
source

I just created a quick sample. Check if you are looking for this. This works at my end.

  • Xaml code

     <StackPanel> <TextBox Text="1/2/3/4" x:Name="txtSource"></TextBox> <TextBox Text="{Binding ElementName=txtSource, Path=Text, Converter={StaticResource txtConv}, ConverterParameter='0'}" x:Name="txtTarget1"></TextBox> <TextBox Text="{Binding ElementName=txtSource, Path=Text, Converter={StaticResource txtConv}, ConverterParameter='1'}" ></TextBox> <TextBox Text="{Binding ElementName=txtSource, Path=Text, Converter={StaticResource txtConv}, ConverterParameter='2'}" ></TextBox> <TextBox Text="{Binding ElementName=txtSource, Path=Text, Converter={StaticResource txtConv}, ConverterParameter='3'}"></TextBox> </StackPanel> 
  • Code for

     public class TextConverter : IValueConverter { #region IValueConverter Members public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string input = (string)value; char[] sep = {'/'}; string[] iparray = input.Split (sep); int index = Int32.Parse((string)parameter); return iparray[index]; } public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException (); } #endregion } 

However, I could not figure out the exact problem using the ConvertBack method. Could you talk about this?

0
source