Reputation: 104721
When declaring converters in a WPF application, should I:
<Application.Resources/>
) so it's available to the entire applicationPage
/Window
/ResourceDictionary
/UserControl
etc. in their Resources
sectionRegarding readability, method 1 seems the best to me, but my question is about performance. Which method is the most resource efficient in terms of performance, memory, etc.?
Upvotes: 17
Views: 8605
Reputation: 5005
@Yogesh answer is awesome. Just for completeness I created a base class for less code:
public abstract class ConverterMarkupExtension : MarkupExtension
{
private static readonly Dictionary<Type, IValueConverter> Converters = new();
protected ConverterMarkupExtension()
{
if (!typeof(IValueConverter).IsAssignableFrom(GetType()))
throw new Exception($"{nameof(ConverterMarkupExtension)} can only be used with {nameof(IValueConverter)}");
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if(!Converters.ContainsKey(GetType()))
Converters.Add(GetType(), (IValueConverter)Activator.CreateInstance(GetType())!);
return Converters[GetType()];
}
}
Upvotes: 0
Reputation: 14608
Well, I just don't declare them in xaml at all. Instead, I additionally derive a converter of mine from MarkupExtension
. Like this:
public class MyValueConverter : MarkupExtension, IValueConverter
{
private static MyValueConverter _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null) _converter = new MyValueConverter();
return _converter;
}
public object Convert
(object value, Type targetType, object parameter, CultureInfo culture) { }
public object ConvertBack
(object value, Type targetType, object parameter, CultureInfo culture) { }
}
This allows me to use my converter anywhere, like this:
Source="{Binding myValue, Converter={converters:MyValueConverter}}"
where converters is the namespace in which I have declared my converter.
Learned this trick from an old stackoverflow thread only.
Upvotes: 57
Reputation: 42364
I have a ResourceDictionary that declares several commonly needed converters, such as a bool-to-visibility converter. I reference this dictionary directly in App.xaml.
I declare other converters that are more specific to a given situation at the Page/Window-level (or in a ResourceDictionary referenced by a Page/Window).
I can't answer the performance question definitively, but I would be very surprised if it made a practical difference in load time or memory usage. Declaring a converter is basically an object instantiation, so it should be very efficient and use very little memory, but I haven't done any profiling to compare app-level vs. window-level performance.
Upvotes: 2
Reputation: 45252
If you only need a converter for the one window, I would put it for the one window (or even for just the container control that holds the control that uses it).
I would argue that this is more maintainable - you can look at the converter declaration and be able to tell what uses it. You know that if you change the controls on that particular page to no longer use the converter, you can take it out of the page's resources without affecting anything else. Conversely, if a converter is an application resource, it's not so simple to ascertain what's using it, if anything.
If the same converter is being used by more than one page, I would still put it under each page resource. Really, it's only one extra line in the XAML.
Anyway, that's my opinion, as of today. I'm expecting another post arguing exactly the opposite. :-)
Upvotes: 0