当前位置:网站首页 / WPF / 正文

2020 WPF 取经之路第12天 - mahapps主题讲解

时间:2020年04月26日 | 作者 : aaronyang | 分类 : WPF | 浏览: 283次 | 评论 0

我研究的是2020年 core3 的mahapps

我们需要个父通知类

  public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected bool Set<T>(ref T field, T newValue = default(T), [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, newValue))
            {
                return false;
            }

            field = newValue;

            this.OnPropertyChanged(propertyName);

            return true;
        }

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

然后实现上篇博客写的一个menu类

    public class AppThemeMenuData : MenuItemModelBase
    {
        public Brush BorderColorBrush { get; set; }

        public Brush ColorBrush { get; set; }
        protected override void DoMenuCommandCommand(object sender)
        {
            ThemeManager.ChangeThemeBaseColor(Application.Current, this.Name);
        }
    }
    public class AppThemeAccentMenuData : MenuItemModelBase
    {
        public Brush BorderColorBrush { get; set; }

        public Brush ColorBrush { get; set; }
        protected override void DoMenuCommandCommand(object sender)
        {
            ThemeManager.ChangeThemeColorScheme(Application.Current, this.Name);
        }
    }

vm修改

    public class MainWindowVM: ViewModelBase
    {
        public List<AppThemeAccentMenuData> AccentColors { get; set; }

        public List<AppThemeMenuData> AppThemes { get; set; }
    }

xaml上,注册4个资源,用menuitem动态生成

<mah:MetroWindow x:Class="AyTestWindowDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" BorderThickness="1" 
        xmlns:local="clr-namespace:AyTestWindowDemo" xmlns:mah="urn:mah" xmlns:zex="urn:controlzex"  mc:Ignorable="d" WindowStartupLocation="CenterScreen" GlowBrush="blue"
        Title="AY测试主题" Height="800" Width="1000" >
    <mah:MetroWindow.Resources>
        <Ellipse x:Key="AppThemeMenuIcon" Width="16" Height="16" x:Shared="False" Fill="{Binding ColorBrush, Mode=OneWay}" Stroke="{Binding BorderColorBrush, Mode=OneWay}" StrokeThickness="1" />
        <Ellipse x:Key="AccentMenuIcon" Width="16" Height="16" x:Shared="False" Fill="{Binding ColorBrush, Mode=OneWay}" />
        <Style x:Key="AppThemeMenuItemStyle" BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
            <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
            <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
            <Setter Property="Icon" Value="{StaticResource AppThemeMenuIcon}" />
        </Style>
        <Style x:Key="AccentColorMenuItemStyle" BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
            <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
            <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
            <Setter Property="Icon" Value="{StaticResource AccentMenuIcon}" />
        </Style>
    </mah:MetroWindow.Resources>
    <Grid Margin="0,0,0,0" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Menu Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Stretch">
            <MenuItem Header="Theme" ItemContainerStyle="{StaticResource AppThemeMenuItemStyle}" ItemsSource="{Binding AppThemes, Mode=OneWay}" />
            <MenuItem Header="Accent" ItemContainerStyle="{StaticResource AccentColorMenuItemStyle}" ItemsSource="{Binding AccentColors, Mode=OneWay}" />
        </Menu>
        <Grid Grid.Row="1" GridService.Rows="40 40 40 40">
            <Button Content="测试" Width="100" Height="20" />
            <StackPanel Orientation="Horizontal" Grid.Row="1">
                <CheckBox Content="测试" />
                <CheckBox Content="测试"  Margin="10,0,0,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Row="2">
                <RadioButton IsChecked="True" Content="测试" />
                <RadioButton Content="测试" />
            </StackPanel>
        </Grid>
   
        <!--<zex:Glow Direction="Bottom" GlowBrush="Red" IsGlow="True" NonActiveGlowBrush="Blue" Height="3"/>-->
    </Grid>
</mah:MetroWindow>


image.png


image.png


image.png

因为我框架把radiobutton什么都删掉了,只保留


MenuItem的事就不讲了,我们直接看ThemeManager

先 Theme 再 Accent

Theme 

ThemeManager 有个EnsureThemes()方法,会读取当前程序集中所包含的 主题文件, 主题文件是放在/themes/里面,以baml结尾的

image.png

        [SecurityCritical]
        private static void OnThemeChanged(Theme newTheme)
        {
            IsThemeChanged?.Invoke(Application.Current, new OnThemeChangedEventArgs(newTheme));
        }


他baml换成了xaml文件后缀,new了一个资源字典,

然后资源字典是否有一个 Theme.Name开头的键名 资源

image.png

符合条件,是一个主题的xaml

image.png

在构造函数创建一个 主题model,方便前台列举出来,这里light开头就是 明亮类型的,dark.开头的就是黑暗主题,当然这里面只提供颜色的切换

image.png

经过这一步,可以获得运行后,dll中存在的主题

主题模板的资源分:

元数据部分

ThemeColor部分

accent color部分

base color部分

核心控件的 color

然后就是base的画刷等等



切换黑白逻辑 断点调试

image.png

切换核心方法

image.png

在运行时,读取了主题的xaml,创建了Theme类型的一个集合,这个集合的每一个Theme都有Resources,就是里面的资源

这里获得老主题资源,在app的resource的MergedDictionaries的文件,添加新主题的Resource,

然后老主题不为空,就移除

然后触发ThemeChanged事件,这在AYUI也有主题改变的事件


app的资源下,merge的有3个,Control,Font,主题文件

Add玩以后有4个文件了

image.png


说白了,我们加一个颜色,就要增加2个 xaml文件



刚刚我把CheckBox的样式删掉了,现在实现下 黑白支持的checkbox


wpf内置控件的样式放在styles下,新增一个Controls.CheckBox.xaml

image.png

模板中的颜色使用DynamicResource引用,这是常规的,缺点是不能用在动画,动画的值只能staticresource

image.png

 AYUI       www.ayjs.net      AY         杨洋原创编写,请不要转载谢谢


那么自己定义的控件呢,一种定义模板,使用DynamicResource

整体思路就是这样,

然后优先控件,可能有问题,那么就实现ThemeManager.IsThemeChanged事件

比如说,WindowCommands.cs控件

public static readonly DependencyProperty ThemeProperty
            = DependencyProperty.Register(
                nameof(Theme),
                typeof(Theme),
                typeof(WindowCommands),
                new PropertyMetadata(Theme.Light, OnThemeChanged));

        private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != e.OldValue && e.NewValue is Theme theme)
            {
                var windowCommands = (WindowCommands)d;

                switch (theme)
                {
                    case Theme.Light:
                    {
                        if (windowCommands.LightTemplate != null)
                        {
                            windowCommands.SetValue(TemplateProperty, windowCommands.LightTemplate);
                        }

                        break;
                    }
                    case Theme.Dark:
                    {
                        if (windowCommands.DarkTemplate != null)
                        {
                            windowCommands.SetValue(TemplateProperty, windowCommands.DarkTemplate);
                        }

                        break;
                    }
                }
            }
        }


在MetroWindow有这样的一段代码

image.png

image.png

image.png

主题改变后,改某些控件的值,然后实现的黑白



 AYUI       www.ayjs.net      AY         杨洋原创编写,请不要转载谢谢


这样子,你应该能看到懂了吧










推荐您阅读更多有关于“WPF4.5,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

抖音号:wpfui,可以看到我的很多作品效果

AYUI8社区版Github地址:前往获取

作者:杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2015年1月17日开始,兴趣学习研究WPF,目前工作繁忙,不接任何活

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

兼容XP到win10,vs2015/2017/2019,最新AYUI:7.6.5.5

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表