📜 ⬆️ ⬇️

XAML Developer Chips: Embedded Converters

Let's analyze an interesting and non-standard scenario of using converters - Inline Converter .
image
Probably, some developers faced the problem that when using converters, information about the presentation, its data context or the visual element to which the binding was made is not transmitted to the converter parameters. On the one hand, this is good, it turns out some protection and separation of logic, it’s not too right in the converter to work directly with the control, on the other hand, in rare cases, it is because of this restriction that one has to go for various tricks.

The good old event model still has not lost its relevance even though a powerful and effective Data Binding mechanism has been developed. Of course, you should not use events to the detriment of progressive development tools, but sometimes their use is convenient and natural.

Why not combine both of these methods? For example, in this way
')
IcompositeConverter
using System.Windows.Data; namespace Aero.Converters.Patterns { public interface ICompositeConverter : IValueConverter { IValueConverter PostConverter { get; set; } object PostConverterParameter { get; set; } } } 


IInlineConverter
 using System; using System.Globalization; using System.Windows.Data; namespace Aero.Converters.Patterns { public class ConverterEventArgs : EventArgs { public object ConvertedValue { get; set; } public object Value { get; private set; } public Type TargetType { get; private set; } public object Parameter { get; private set; } public CultureInfo Culture { get; private set; } public ConverterEventArgs(object value, Type targetType, object parameter, CultureInfo culture) { TargetType = targetType; Parameter = parameter; Culture = culture; Value = value; } } public interface IInlineConverter : IValueConverter { event EventHandler<ConverterEventArgs> Converting; event EventHandler<ConverterEventArgs> ConvertingBack; } //public interface IInlineConverter : IValueConverter //{ // event Func<object, Type, object, CultureInfo, object> Converting; // event Func<object, Type, object, CultureInfo, object> ConvertingBack; //} } 


Inlineconverter
 using System; using System.Globalization; using System.Windows.Data; using Aero.Converters.Patterns; namespace Aero.Converters { public class InlineConverter : IInlineConverter, ICompositeConverter { public IValueConverter PostConverter { get; set; } public object PostConverterParameter { get; set; } public event EventHandler<ConverterEventArgs> Converting; public event EventHandler<ConverterEventArgs> ConvertingBack; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var args = new ConverterEventArgs(value, targetType, parameter, culture); var handler = Converting; if (handler != null) handler(this, args); return PostConverter == null ? args.ConvertedValue : PostConverter.Convert(args.ConvertedValue, targetType, PostConverterParameter, culture); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var args = new ConverterEventArgs(value, targetType, parameter, culture); var handler = ConvertingBack; if (handler != null) handler(this, args); return PostConverter == null ? args.ConvertedValue : PostConverter.ConvertBack(args.ConvertedValue, targetType, PostConverterParameter, culture); } } } 


What do we get? We need to embed the converter instance into the control or view resources, and in the Code Behind of the submission, make the necessary handlers for the Converting and ConvertingBack events, after which these events will be triggered during the triggering of the binding, and in the handlers through this a view with a visual tree and a data context! Unexpectedly, there was a great deal of freedom of action, moreover, everything remained ideologically correct, because the interface logic was not included in the converter itself, and it remained only in the Behain code.

Here is a simple example of using this approach.

 <Grid> <Grid.Resources> <InlineConverter x:Key="InlineConverter" Converting="InlineConverter_OnConverting"/> </Grid.Resources> <TextBlock Text="{Binding Number, Converter={StaticResource InlineConverter}}"/> </Grid> 

  private void InlineConverter_OnConverting(object sender, ConverterEventArgs e) { e.ConvertedValue = string.Format("Title: {0} \nDataContext:\n{1} \nConverter Value: {2}", Title, DataContext, e.Value); } 

The additional use of the Composite Converter [ ICompositeConverter ] pattern allows you to combine various converters into chains, modifying logic, without the need to create new classes.

You can see Inline Converter and some others in action in the demonstration project HelloAero of the Aero Framework library [ backup link ].

Thank you for attention!

PS Previous article on Dynamic Grid

Update
Application
The need for a method in practice arises infrequently, but at the same time it can make life extremely easy in “uncomfortable” situations. For example, this way you can replace MultiBinding when porting code from WPF to Windows Phone , since multiple binding is not supported on the mobile platform. Just remember about embedded converters and at the right time you will find a use for them.

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


All Articles