简体   繁体   English

避免可重用WPF控件中的XAML资源键冲突

[英]Avoiding XAML resource key conflicts in reusable WPF controls

I'm developing a WPF control and I have no control over applications where it will be used. 我正在开发一个WPF控件,我无法控制将要使用它的应用程序。 Some XAML resource dictionary keys are obviously unique for my control, for example, <Style TargetType="{x:Type MyControl}"> , so there is no risk of conflicts. 某些XAML资源字典键显然对我的控件是唯一的,例如, <Style TargetType="{x:Type MyControl}"> ,因此不存在冲突的风险。

However, I need to use non-unique objects like BooleanToVisibilityConverter too. 但是,我也需要使用像BooleanToVisibilityConverter这样的非唯一对象。 If I add it with the "BooleanToVisibilityConverter" key, it is possible (and likely) that the consumer of the control who includes my resource dictionary has already defined a similar converter in their code, probably with a different behavior. 如果我使用"BooleanToVisibilityConverter"键添加它,则可能(并且可能)包含我的资源字典的控件的使用者已经在其代码中定义了类似的转换器,可能具有不同的行为。

Standard controls are avoiding conflicts somehow. 标准控制以某种方式避免冲突。 There is a <BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" /> in Aero.NormalColor.xaml which is not visible for WPF applications. <BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />有一个<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />Aero.NormalColor.xaml WPF应用程序不可见。 However, I don't know how to achieve this. 但是,我不知道如何实现这一目标。

How to avoid resource name conflicts? 如何避免资源名称冲突? How to make my resource names "local" for my control? 如何让我的资源名称“本地”为我的控件?

Usually WPF controls are designed in a way which doesn't require customer to include any resource dictionaries explicitly. 通常,WPF控件的设计方式不要求客户明确包含任何资源字典。 Assembly with WPF controls has ThemeInfo attribute: 使用WPF控件进行ThemeInfo具有ThemeInfo属性:

[assembly: ThemeInfo(
    ResourceDictionaryLocation.None,
    ResourceDictionaryLocation.SourceAssembly
)]

which specifies where to look for default styles, and default styles are written to Themes/Generic.xaml file. 它指定了查找默认样式的位置,并将默认样式写入Themes/Generic.xaml文件。

Anyway, since resource dictionary key is an object , you can define absolutely unique keys in some internal static class: 无论如何,由于资源字典键是一个object ,您可以在某个内部静态类中定义绝对唯一的键:

internal static class ResourceKeys
{
    public static readonly object BooleanToVisibilityConverter = new object();
}

And use them in XAML instead of strings: 并在XAML而不是字符串中使用它们:

<ResourceDictionary xmlns:local="clr-namespace:YOUR_NAMESPACE_HERE">
    <BooleanToVisibilityConverter x:Key="{x:Static local:ResourceKeys.BooleanToVisibilityConverter}" />
</ResourceDictionary>

one solution to avoid keys is, use the ValueConverter as singleton 一个避免键的解决方案是,使用ValueConverter作为单例

public sealed class SingletonValueConverter : IValueConverter
{
    private static SingletonValueConverter instance;

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static SingletonValueConverter() {
    }

    private SingletonValueConverter() {
    }

    public static SingletonValueConverter Instance {
    get { return instance ?? (instance = new SingletonValueConverter()); }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        return ...
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return ...
    }
}

now you can use the ValueConverter like this 现在您可以像这样使用ValueConverter

<TextBlock Text="{Binding TestProperty, Converter={x:Static local:SingletonValueConverter.Instance}}" />

hope this helps 希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM