I am binding a dependency property to textboxex in WPF. The property is a string that has some values separated by \'/\' (example: \"1/2/3/4\" ). I need to bind individual v
Update
You have probably solved your issue already with the help of Vlad, I just thought I should add another way of actually getting the source value in the converter.
First you could make your converter derive from DependencyObject
so you can add a Dependency Property to it which we shall bind to
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, a Converter doesn't have a DataContext
so the Binding won't work out of the box but you can use Josh Smith's excellent DataContextSpy
: Artificial 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 to this, see the following thread
The way to access binding source in ConvertBack()?
Edit
Using the solution by Dr.WPF, you could supply both the string index and the source TextBox
to the converter with this (perhaps a little verbose) sample code
<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 could 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;
//...
}
I just built up quick sample. Please check if you are looking for the same. This is working 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 Behind
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 couldn't understand the exact issue with ConvertBack
method. Could you please elaborate on this?
In most cases, you can safely make ConvertBack
just throw NotImplementedException
.
Indeed, you just haven't got enough information to recreate the source value from its part!
If you really need the back conversion (e.g., if you use two-direction binding), I would split the property into 3 strings in the view model (the class used in DataContext
), and bind to them separately.
Would you be better off using an IMultiValueConverter and a MultiBinding?
public interface IMultiValueConverter
{
object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);
object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);
}
In this case, if you really want to be able to edit the constituents, you could represent your number by a more complex object which allows you to access its 4 constituent parts through an indexer. That way it's just a simple binding and the object that keeps the 4 parts is accessed and can piece together the whole number:
public class MyNumber {
public int this[int index] {
get { /**/ } set { /**/ }
}
public string FullNumber { get { /**/ } }
}
<TextBox Text={Binding MyNumber[0]}" />