wpf - 如何向用户控件添加更多资源

标签 wpf xaml wpf-controls resourcedictionary

我们可以向 UserControl 添加新资源吗?在使用时,不会删除 UserControl 的资源已经定义了自己?

例如,这里是 UserControl :

<UserControl x:Class="MyControl">
  <UserControl.Resources>
    <!--Resource1-->
    <!--Resource2-->
  </UserControl.Resources>
</UserControl>

我在 MainWindow 中使用此控件:

<MainWindow>
  <local:MyControl>
    <local:MyControl.Resources>
      <!--Resource3-->
    </local:MyControl.Resources>
  </local:MyControl>
</MainWindow>

这样做会清除 Resource1 和 Resource2,只剩下 Resource3。我已经尝试过<ResourceDictionary.MergedDictionaries>同样,这也有同样的效果。我正在寻找一种将 Resource3 添加到现有资源列表的方法。

最佳答案

据我所知,没有内置的可能性可以做到这一点。但您可以通过代码或附加属性来做到这一点。例如,让我们定义这样的属性:

public static class ResourceExtensions {
    public static readonly DependencyProperty AdditionalResourcesProperty = DependencyProperty.RegisterAttached(
        "AdditionalResources", typeof(ResourceDictionary), typeof(ResourceExtensions), new PropertyMetadata(null, OnAdditionalResourcesChanged));

    private static void OnAdditionalResourcesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var fe = d as FrameworkElement;
        if (fe == null)
            throw new Exception("Cannot add resources to type " + d.GetType());
        if (fe.Resources == null)
            fe.Resources = new ResourceDictionary();
        var dict = e.NewValue as ResourceDictionary;
        if (dict != null) {                                
            foreach (DictionaryEntry resource in dict) {
                fe.Resources[resource.Key] = resource.Value;
            }
        }
    }

    public static void SetAdditionalResources(DependencyObject element, ResourceDictionary value) {
        element.SetValue(AdditionalResourcesProperty, value);
    }

    public static ResourceDictionary GetAdditionalResources(DependencyObject element) {
        return (ResourceDictionary) element.GetValue(AdditionalResourcesProperty);
    }
}

它将执行的操作是获取资源字典并将其中的所有值复制到目标控件的资源字典(覆盖现有资源的值)。用法是:

<Window.Resources>
    <ResourceDictionary>
        <!-- This is resource dictionary to merge with target -->
        <ResourceDictionary x:Key="overrideResources">
            <Brush x:Key="foreground">Yellow</Brush>
        </ResourceDictionary>
    </ResourceDictionary>
</Window.Resources>
<wpfApplication1:UserControl1 wpfApplication1:ResourceExtensions.AdditionalResources="{StaticResource overrideResources}"/>

请注意,为了帮助解决您在评论中链接的另一个问题 - 您需要使用 DynamicResource 扩展而不是 StaticResource 来使用资源:

<UserControl.Resources>
    <Brush x:Key="foreground">Red</Brush>
    <Style x:Key="test" TargetType="TextBlock">
        <!-- Note DynamicResource here -->
        <Setter Property="Foreground" Value="{DynamicResource foreground}" />
    </Style>
</UserControl.Resources>
<StackPanel>
    <TextBlock Text="test" FontSize="12" Style="{StaticResource test}" />
</StackPanel>

如果我将带有附加属性的上述方法应用于此UserControl - 其中的文本将变成黄色(红色),因为Brush与键foreground 被覆盖,但带有 test 键的 Style 保持不变,我使用了 DynamicResource。如果我使用 StaticResource 相反,资源字典中的资源仍然会发生变化,但控件不会反射(reflect)该变化,因为使用 StaticResource 它不会监视资源中的变化。

关于wpf - 如何向用户控件添加更多资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42874082/

相关文章:

WPF,将 Path.DataProperty 转换为 Segment 对象

c# - WPF 中的分辨率独立性如何工作?

wpf - 如何设置 WPF 扩展器标题的样式?

c# - 将 WPF 元素本身绑定(bind)到 View 模型对象

c# - 更改 ListBox 的 UniformGrid 列数的最佳方法是什么?

validation - Wpf 组合框限制为列表

c# - 如何设置默认路径,然后按 WPF 中的 ShowDialog 按钮?

c# - RadGridView 模板选择器

c# - Windows 10 通用编译绑定(bind) (x :Bind) conflict with ViewModel

wpf-controls - 如何将键盘快捷键分配给 WPF 功能区控件?