IValueConverter maintains state if it cannot set the converter parameter

I have an IValueConverter that converts an enum value to a localized string through a lookup table and vice versa. To find the correct table, you first need to know the name of the table. When the enumeration value is transferred to the converter via the Convert method, this can be found. When a string is passed to the converter through the ConvertBack method, this is not (enumeration types are unique, but string values ​​are not).

The converter is used in DataTemplates for editors used in the data grid and property grid.

In one case, you can pass the table name as ConverterParameter, since a DataTemplate is dynamically generated. In another case, this is not possible. My current solution searches for the table name in the Convert method and saves it for use in the ConvertBack method (i.e. IValueConverter maintains state between Convert and ConvertBack calls). This suggests that Convert will always be called before ConvertBack, which does not seem like a safe guess. I use every instance of the converter binding:

<converters:EnumToStringConverter x:Key="EnumToStringConverter" x:Shared="False"/> 

Is it safe, or is it coming back to haunt me? Converter methods are as follows:

 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 that I tried to see, if possible, is to create a dependency property in the converter and somehow bind it to the collection name. Is there a way to set the converter's DataContext to the same as the binding it acts on? The converter is currently a StaticResource, so the DataContext does not.

thanks

+4
source share
2 answers

Converters not allowed to be DependencyObject in WPF, as they will not be able to provide their properties, which can change dynamically.

The code below converts a Key to Value and Value to Key using a dynamically linked 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> 

WITH#

  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; } } } } 
+3
source

You can always bind your meaning to just "." this will then give you your DataContext in the converter, then you can save the state in this object.

0
source

Source: https://habr.com/ru/post/1442008/


All Articles