Reputation: 77
I have a IValueConverter which converts an enum value to a localised string via a lookup table, and vice versa. To find the correct table it first needs to know the name of the table. When the enum value is passed into the converter via the Convert method it is possible to find this. When the string is passed into the converter via the ConvertBack method it isn't (enum types are unique, but the string values are not).
The converter is used on DataTemplates for editors used in a Data Grid and a Property Grid.
In one case it is possible to pass the name of the table in as the ConverterParameter, as the DataTemplate is dynamically generated. In the other it does not seem possible to do this. My current solution looks up the table name in the Convert method and stores it for use in the ConvertBack method (i.e. the IValueConverter maintains state between calls to Convert and ConvertBack). This assumes that Convert will always be called before ConvertBack, which does not seem like a safe assumption. I'm using a per binding instance of the converter:
<converters:EnumToStringConverter x:Key="EnumToStringConverter" x:Shared="False"/>
Is this safe or will this come back to haunt me? The converter methods look like this:
private string listName = null;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter == null)
{
parameter = ListManager.FindListNameFromObject(value);
}
listName = (string)parameter;
return ListManager.GetKeyFromValue((string)parameter, value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter == null)
{
parameter = listName;
}
return ListManager.GetValueFromKey((string)parameter, (string)value);
}
An alternative I've been trying to see if is possible, is to create a dependency property on the converter, and bind this to the name of the collection somehow. Is there a way to set the DataContext of the converter to be the same as the binding it is acting on? Currently the converter is a StaticResource so has no DataContext.
Thanks
Upvotes: 4
Views: 1846
Reputation: 19885
Converters
are not allowed to be DependencyObject
s in WPF as they wouldnt be able to provide biding to their properties which could change dynamically.
Code below converts a Key
to Value
& Value
to Key
using dynamically bound Dictionary
.
XAML
<StackPanel>
<StackPanel.Resources>
<FrameworkElement x:key="ProxyElement"
DataContext="{Binding}" />
</StackPanel.Resources>
<ContentControl Visibility="Collapsed"
DataContext="{Binding MyDictionary}"
Content="{StaticResource ProxyElement}" />
<TextBox Text="{Binding Key,
Converter={StaticResource MyConverter},
ConverterParameter={StaticResource ProxyElement}}"/>
</StackPanel>
C#
public class MyConverter : IValueConverter
{
object Convert(value, parameter ..)
{
var dict
= ((FrameworkElement)parameter).DataContext
as Dictionary<string, string>)parameter;
return (dict[value.ToString()];
}
object ConvertBack (value, parameter ..)
{
var dict
= ((FrameworkElement)parameter).DataContext
as Dictionary<string, string>)parameter;
foreach(var item in dict)
{
if (item.Value == value)
{
return item.Key;
}
}
}
}
Upvotes: 5
Reputation: 3168
You could always Bind your value to just "." this would then give you your DataContext in the converter then you could persist the state in that object instead.
Upvotes: 0