Как проще всего делить ресурсы между UserControls в библиотеке управления пользователями WPF? - PullRequest
8 голосов
/ 21 июля 2011

В нем есть библиотека пользовательских элементов управления WPF и два (или более) пользовательских элемента управления.Мне нужно использовать один и тот же стиль в обоих пользовательских элементах управления.Как я могу поделиться этим стилем?Например:

Это стиль:

<Style x:Key="customLabelStyle" TargetType="Label">
    ...
</Style>

Пользовательский контроль A:

<UserControl x:Class="Edu.Wpf.Example.UserControlA"
   ...xmlns stuff... >
   <Grid>
      ... some xaml markup...
      <Label Style="{StaticResource customLabelStyle}"/>
   </Grid>
</UserControl>

UserControl B:

 <UserControl x:Class="Edu.Wpf.Example.UserControlB"
   ...xmlns stuff... >
   <Grid>
      ... some another xaml markup...
      <Label Style="{StaticResource customLabelStyle}"/>
   </Grid>
</UserControl>

Так какя могу поделиться этим стилем между пользовательскими элементами управления в библиотеке без использования словаря ресурсов приложения app.xaml?

ОБНОВЛЕНИЕ

Я могу добавить Themes \ Generic.xaml вмоя библиотека и определить стиль там.Но в этом случае я должен использовать ComponentResourceKey в качестве ключа стиля.Правильно?Это длинное и не очень удобное выражение ...

Ответы [ 3 ]

14 голосов
/ 21 июля 2011

Допустим, у вас есть один ресурс, определяющий цвета, например:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Color A="#FF" R="#FF" G="#22" B="#11" x:Key="MyRed"/>
    <Color A="#FF" R="#00" G="#FF" B="#21" x:Key="MyGreen"/>
    <Color A="#FF" R="#00" G="#22" B="#FF" x:Key="MyBlue" />


    <SolidColorBrush x:Key="MyGreenBrush" Color="{StaticResource MyGreen}"/>
    <SolidColorBrush x:Key="MyRedBrush" Color="{StaticResource MyRed}"/>
    <SolidColorBrush x:Key="MyBlueBrush" Color="{StaticResource MyBlue}"/>
</ResourceDictionary>

И еще один, определяющий некоторые базовые стили, такие как:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type TextBlock}" x:Key="PocTextBlock">
        <Setter Property="FontSize" Value="16"/>
    </Style>

    <Style TargetType="{x:Type TextBox}" x:Key="MyTextBox">
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="Foreground" Value="{DynamicResource MyGreenBrush}"/>
    </Style>

    <Style TargetType="{x:Type TextBlock}" x:Key="MyResultTextBlock">
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="{DynamicResource MyGreenBrush}"/>
    </Style>

    <Style TargetType="{x:Type Border}" x:Key="MyBorder">
        <Setter Property="BorderBrush" Value="{DynamicResource MyGreenBrush}"/>
        <Setter Property="BorderThickness" Value="4"/>
        <Setter Property="CornerRadius" Value="5"/>
    </Style>
</ResourceDictionary>

Затем вы можете добавить свои ресурсы втег App.xaml Application.Resources, как показано здесь:

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="OtherStyles.xaml"/>
                <ResourceDictionary Source="Colors.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Затем во всех ваших пользовательских элементах управления вы можете использовать стили или кисти в качестве StaticResources, как показывает пример кода.

2 голосов
/ 21 июля 2011

Вы можете определить общие ресурсы в отдельном ResourceDictionary, а затем объединить их с ресурсами UserControl, используя MergedDictionaries .

1 голос
/ 02 августа 2011

Я нашел решение, которое работает и во время разработки (по крайней мере, в VS2010):

public static class Resource
{
    private static readonly Dictionary<Uri, ResourceDictionary> SharedDictinaries = new Dictionary<Uri, ResourceDictionary>();

    private static void onMergedDictionaryChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
        FrameworkElement el = source as FrameworkElement;
        if (el == null)
            return;

        Uri resourceLocator = new Uri(GetMergedDictionary(source), UriKind.Relative);
        ResourceDictionary dictionary;
        if (SharedDictinaries.ContainsKey(resourceLocator))
            dictionary = SharedDictinaries[resourceLocator];
        else
        {
            dictionary = (ResourceDictionary)Application.LoadComponent(resourceLocator);
            SharedDictinaries.Add(resourceLocator, dictionary);
        }

        el.Resources.MergedDictionaries.Add(dictionary);
    }

    public static readonly DependencyProperty MergedDictionaryProperty =
        DependencyProperty.RegisterAttached("MergedDictionary", typeof (String), typeof (Resource), new FrameworkPropertyMetadata(null, onMergedDictionaryChanged));

    [AttachedPropertyBrowsableForType(typeof(FrameworkElement))]
    public static String GetMergedDictionary(DependencyObject source)
    {
        return (String) source.GetValue(MergedDictionaryProperty);
    }

    public static void SetMergedDictionary(DependencyObject source, String value)
    {
        source.SetValue(MergedDictionaryProperty, value);
    }
}

Это присоединенное свойство может быть применено к FrameworkElement. Представьте, что customLabelStyle определен в словаре Styles.xaml в проекте Edu.Wpf.Example. Таким образом, этот стиль может быть применен следующим образом:

<UserControl x:Class="Edu.Wpf.Example.UserControlA"
     ...
     xmlns:res="clr-namespace:Edu.Wpf.Example.Resources"
     res:Resource.MergedDictionary="/Edu.Wpf.Example;component/Resources/Styles.xaml">
     ...
     <Label Style="{StaticResource customLabelStyle}"/>
</UserControl>
...