WPF for instance value converter binding?

How do you ensure that a new instance of a value converter is created for each binding in which it is used?

+4
source share
5 answers

You need to specify x:Shared="False" on the converter resource. Here is an example:

 <BooleanToVisibilityConverter x:Key="MyConverter" x:Shared="False"/> 
+16
source

You can create a separate resource in each control:

  <TextBox> <TextBox.Resources> <Converters:VisibilityConverter x:Key="conv"/> </TextBox.Resources> <TextBox.Text> <Binding Converter="{StaticResource conv}"/> </TextBox.Text> </TextBox> 
+2
source

Why? It must be deterministic and not know a single state, except for the one that is transmitted to it through its parameters. I used value converters to store a static list of images (the value is converted to an image), and this works fine even when the same converter is used on multiple columns in a datagrid with thousands of rows. (Please note that the inverter still does not know about any external state).

In any case, see if this answers your question: Are value converters created for each binding in WPF?

+1
source

If you put converters in resources and refer to them through the search {StaticResource ConverterName} , then they are launched only once per instance of the resource dictionary.

But it’s best to inherit your converters from MarkupExtension and use them directly, rather than adding them to resources and referencing them.

Here is an example of such a base class:

http://www.snippetsource.net/Snippet/18/base-class-for-valueconverters-in-wpf

Hi Christian

0
source

Inherit from MarkupExtension , and then create your own converter in the constructor.

  public override object ProvideValue(IServiceProvider serviceProvider) { _converter = new FlagsToBoolConverter(); return _converter; } 

Here is a complete example. This is the flag converter that had to be installed in order to keep the original value for ConvertBack.

 using System; using System.Globalization; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Data; using System.Windows.Markup; namespace Something { public class FlagsToBoolConverter : MarkupExtension, IValueConverter { private FlagsToBoolConverter _converter; public override object ProvideValue(IServiceProvider serviceProvider) { _converter = new FlagsToBoolConverter(); return _converter; } private ulong _sourceValue; public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) { try { var type = value.GetType(); if (type.IsEnum) { ulong mask = (ulong)System.Convert.ChangeType(Enum.Parse(type, (string)parameter), typeof(ulong)); _sourceValue = (ulong)System.Convert.ChangeType(Enum.Parse(type, value.ToString()), typeof(ulong)); return ((mask & _sourceValue) != 0); } return value; } catch (Exception ex) { Console.WriteLine("FlagsEnumValueConverter: Invalid Cast(to) Value={0} Type={1} Param={2} Exception{3}", value, targetType, parameter, ex); } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { try { if (targetType.IsEnum) { var original = this._sourceValue; var originalEnum = Enum.Parse(targetType, original.ToString()); var maskEnum = Enum.Parse(targetType, (string)parameter); var mask = (ulong)System.Convert.ChangeType(maskEnum, typeof(ulong)); _sourceValue ^= mask; var sourceEnum = Enum.Parse(targetType, _sourceValue.ToString()); Console.WriteLine($"Modified Value: {original} ({originalEnum}) by Mask {mask} ({maskEnum}) Result = {_sourceValue} ({sourceEnum})"); return sourceEnum; } return value; } catch (Exception ex) { Console.WriteLine("FlagsEnumValueConverter: Invalid Cast(from) Value={0} Type={1} Param={2} Exception{3}", value, targetType, parameter, ex); } return value; } } } 

The prefix must be declared xmlns:src="clr-namespace:Something" . And then in your binding, replace the regular converter with Converter={src:FlagsToBoolConverter}

  <CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagA, Converter={src:FlagsToBoolConverter}}">FlagA</CheckBox> <CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagB, Converter={src:FlagsToBoolConverter}}">FlagB</CheckBox> <CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagC, Converter={src:FlagsToBoolConverter}}">FlagC</CheckBox> 
0
source

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


All Articles