Слияние стиля управления с глобальным стилем, заданным другим проектом, динамически - PullRequest
0 голосов
/ 07 марта 2011

У меня сейчас проблема.Я использую WPF. Темы, которые я нашел в codeplex, он позволяет мне менять тему моего приложения.

Итак, я импортировал проект и получил все нормально, но для некоторого контроля, скажем, у моего treeViewItem, у меня былоему уже задан стиль, который переопределяет глобальные стили.

У меня есть следующий код после исследования, но он все равно не будет работать.

<TreeView Name="_tvTreeView" Grid.Row="1" >
       <TreeView.ItemContainerStyle>
           <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
               <EventSetter Event="MouseDoubleClick" Handler="tvTreeView_PreviewMouseDoubleClick"/>
               <EventSetter Event="MouseDown" Handler="tvTreeView_MouseDown"/>
           </Style>
       </TreeView.ItemContainerStyle>
</TreeView>

На основе работ, если я вручную добавлювосстановить файл в словаре слияния app.xaml моего основного проекта.

Но проект WPF.Themes позволяет мне динамически изменять тему, выполняя это.

  public static void ApplyTheme(this ContentControl control, string theme)
  {
      ResourceDictionary dictionary = ThemeManager.GetThemeResourceDictionary(theme);

      control.Resources.MergedDictionaries.Clear();
      if (dictionary != null)
          control.Resources.MergedDictionaries.Add(dictionary);
  }

Имея приведенный выше код, не объединяет глобальные стили и мои установщики событий.Если бы я вручную ссылался на тему в app.xaml, то «BasedOn» включался бы и работал, но «BasedOn», похоже, не работал, если я устанавливал mergedDictionaries динамически.

Есть ли способ получитьэто работает без добавления темы в app.xaml.

Спасибо и С уважением,

1 Ответ

1 голос
/ 28 июня 2011

Свойство BaseOn стиля не может быть установлено с DynamicResource, со StaticResource оно будет запечатано при применении к элементу управления.

Вы должны объединить стиль, когда глобальный стиль изменился, попробуйте эти коды:

public class Behavior
{
    #region AutoMergeStyle

    public static readonly DependencyProperty AutoMergeStyleProperty =
        DependencyProperty.RegisterAttached("AutoMergeStyle", typeof(bool), typeof(Behavior),
            new FrameworkPropertyMetadata((bool)false,
                new PropertyChangedCallback(OnAutoMergeStyleChanged)));

    public static bool GetAutoMergeStyle(DependencyObject d)
    {
        return (bool)d.GetValue(AutoMergeStyleProperty);
    }

    public static void SetAutoMergeStyle(DependencyObject d, bool value)
    {
        d.SetValue(AutoMergeStyleProperty, value);
    }

    private static void OnAutoMergeStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.OldValue == e.NewValue)
        {
            return;
        }

        Control control = d as Control;
        if (control == null)
        {
            throw new NotSupportedException("AutoMergeStyle can only used in Control");
        }

        if ((bool)e.NewValue)
        {
            Type type = d.GetType();
            control.SetResourceReference(Behavior.BaseOnStyleProperty, type);
        }
        else
        {
            control.ClearValue(Behavior.BaseOnStyleProperty);
        }
    }

    #endregion

    #region BaseOnStyle

    public static readonly DependencyProperty BaseOnStyleProperty =
        DependencyProperty.RegisterAttached("BaseOnStyle", typeof(Style), typeof(Behavior),
            new FrameworkPropertyMetadata((Style)null,
                new PropertyChangedCallback(OnBaseOnStyleChanged)));

    public static Style GetBaseOnStyle(DependencyObject d)
    {
        return (Style)d.GetValue(BaseOnStyleProperty);
    }

    public static void SetBaseOnStyle(DependencyObject d, Style value)
    {
        d.SetValue(BaseOnStyleProperty, value);
    }

    private static void OnBaseOnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.OldValue == e.NewValue)
        {
            return;
        }

        Control control = d as Control;
        if (control == null)
        {
            throw new NotSupportedException("BaseOnStyle can only used in Control");
        }

        Style baseOnStyle = e.NewValue as Style;
        Style originalStyle = GetOriginalStyle(control);
        if (originalStyle == null)
        {
            originalStyle = control.Style;
            SetOriginalStyle(control, originalStyle);
        }
        Style newStyle = originalStyle;

        if (originalStyle.IsSealed)
        {
            newStyle = new Style();
            newStyle.TargetType = originalStyle.TargetType;

            //1. Copy resources, setters, triggers
            newStyle.Resources = originalStyle.Resources;
            foreach (var st in originalStyle.Setters)
            {
                newStyle.Setters.Add(st);
            }
            foreach (var tg in originalStyle.Triggers)
            {
                newStyle.Triggers.Add(tg);
            }

            //2. Set BaseOn Style
            newStyle.BasedOn = baseOnStyle;
        }
        else
        {
            originalStyle.BasedOn = baseOnStyle;
        }

        control.Style = newStyle;
    }

    #endregion

    #region OriginalStyle

    public static readonly DependencyProperty OriginalStyleProperty =
        DependencyProperty.RegisterAttached("OriginalStyle", typeof(Style), typeof(Behavior),
            new FrameworkPropertyMetadata((Style)null));

    public static Style GetOriginalStyle(DependencyObject d)
    {
        return (Style)d.GetValue(OriginalStyleProperty);
    }

    public static void SetOriginalStyle(DependencyObject d, Style value)
    {
        d.SetValue(OriginalStyleProperty, value);
    }

    #endregion
}

Добавить прикрепленное свойство AutoMergeStyle к xaml:

<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
               <EventSetter Event="MouseDoubleClick" Handler="tvTreeView_PreviewMouseDoubleClick"/>
               <EventSetter Event="MouseDown" Handler="tvTreeView_MouseDown"/>
               <Setter Property="Behavior.AutoMergeStyle" Property="True"/>
</Style>
...