wpf 我应该在App.xaml中声明转换器还是作为每个文件的资源声明转换器?

vlf7wbxs  于 2023-06-30  发布在  其他
关注(0)|答案(4)|浏览(129)

在WPF应用程序中声明转换器时,我应该:
1.在App.xaml中声明 * 所有 * 我的转换器(即在<Application.Resources/>中),因此它可用于整个应用程序
1.仅声明每个Page/Window/ResourceDictionary/UserControl等所需的转换器。在其Resources部分中
1.完全是另外一回事
关于可读性,方法1对我来说似乎是最好的,但我的问题是关于性能的。在性能、内存等方面,哪种方法的资源效率最高?

mwyxok5s

mwyxok5s1#

好吧,我只是根本不在xaml中声明它们。相反,我还从MarkupExtension派生了一个转换器。像这样:

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) { }
}

这允许我在任何地方使用转换器,如下所示:

Source="{Binding myValue, Converter={converters:MyValueConverter}}"

其中converters是我声明转换器的命名空间。
从一个旧的stackoverflow线程中学习到这个技巧。

j9per5c4

j9per5c42#

我有一个ResourceDictionary,它声明了几个常用的转换器,比如bool-to-visibility转换器。我在App. xaml中直接引用了这个字典。
我在Page/Window级别(或在Page/Window引用的ResourceDictionary中)声明了其他更特定于给定情况的转换器。
我不能明确地回答性能问题,但如果它在加载时间或内存使用方面有实际的不同,我会非常惊讶。声明一个转换器基本上就是一个对象示例化,所以它应该非常高效,并且使用很少的内存,但是我还没有做任何分析来比较应用程序级与窗口级性能。

c2e8gylq

c2e8gylq3#

如果你只需要一个窗口的转换器,我会把它放在一个窗口(甚至只是容器控件,持有使用它的控件)。
我认为这更易于维护-您可以查看转换器声明,并能够告诉什么使用它。您知道,如果您将该特定页面上的控件更改为不再使用转换器,则可以将其从页面的资源中取出,而不会影响其他任何内容。相反,如果转换器是一个应用程序资源,那么要确定是什么在使用它(如果有的话)就不那么简单了。
如果同一个转换器被多个页面使用,我将still放在每个页面资源下。实际上,它只是XAML中多了一行。
无论如何,这是我的观点,从今天开始。我期待着另一个帖子,争论完全相反。:—)

wsxa1bj1

wsxa1bj14#

@Yogesh的回答很棒。为了完整起见,我创建了一个基类,以减少代码:

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()];
    }
}

相关问题