【问题标题】:Merge control style with global style set by another project dynamically将控件样式与另一个项目设置的全局样式动态合并
【发布时间】:2011-07-10 12:53:06
【问题描述】:

我目前面临一个问题。我正在使用我在 codeplex 上找到的 WPF.Themes,它允许我更改应用程序的主题。

所以我导入了项目并让它一切正常,但是对于某些控件,比如我的 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”会启动并工作,但如果我动态设置 mergeDictionaries,“BasedOn”似乎不起作用。

有没有一种方法可以在不将主题添加到 app.xaml 的情况下使其工作。

感谢和问候,

【问题讨论】:

    标签: wpf xaml binding styles


    【解决方案1】:

    style的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>
    

    【讨论】:

      猜你喜欢
      • 2022-11-12
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      • 2019-07-14
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多