wpf – 如何向UserControl添加更多资源

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

所以对于exmaple,这是一个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 – 其中的文本将变为黄色(呈红色),因为带有键前景的画笔被覆盖但带有键测试的样式保持不变,我使用了DynamicResource.如果我使用StaticResource – 资源字典中的资源仍然会改变,但控制不会反映这种改变,因为使用StaticResource它不会监视资源的变化.

点赞