MaterialDesign WPF菜单按钮样式问题:切换后无法重置原样式
你遇到的核心问题是把按钮的Style设为null时,它会回到WPF的默认基础样式,而不是Material Design的原始按钮样式。这就是为什么你重置后按钮看起来不对的原因。下面给你几种解决方案,从简单到更优雅的都有:
方案1:保存原始样式,切换时复用
首先在窗口/用户控件初始化时,把每个按钮的Material Design原始样式保存下来,之后需要重置时赋值回去,而不是设为null。
步骤1:保存原始样式
在你的窗口构造函数里添加代码:
private Style _originalUserStyle; private Style _originalAutoStyle; private Style _originalClientStyle; private Style _originalFailureStyle; private Style _originalSettingsStyle; public YourWindowName() { InitializeComponent(); // 保存每个按钮的初始Material Design样式 _originalUserStyle = User_B.Style; _originalAutoStyle = Auto_B.Style; _originalClientStyle = Clien_B.Style; _originalFailureStyle = Failure_B.Style; _originalSettingsStyle = Settings_B.Style; }
步骤2:修改点击事件代码
创建选中样式时,基于原始样式继承(这样能保留Material Design按钮的hover、press等交互状态),重置时用保存的原始样式:
private void User_B_Click(object sender, RoutedEventArgs e) { // 基于原始样式创建选中样式,保留Material Design的交互特性 Style selectedStyle = new Style(typeof(Button), _originalUserStyle); selectedStyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030")))); selectedStyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000")))); // 应用选中样式到当前按钮,其他按钮重置为原始样式 User_B.Style = selectedStyle; Auto_B.Style = _originalAutoStyle; Clien_B.Style = _originalClientStyle; Failure_B.Style = _originalFailureStyle; Settings_B.Style = _originalSettingsStyle; // 导航逻辑 Main.Navigate(new YourUserPage()); } private void Auto_B_Click(object sender, RoutedEventArgs e) { Style selectedStyle = new Style(typeof(Button), _originalAutoStyle); selectedStyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030")))); selectedStyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000")))); Auto_B.Style = selectedStyle; User_B.Style = _originalUserStyle; Clien_B.Style = _originalClientStyle; Failure_B.Style = _originalFailureStyle; Settings_B.Style = _originalSettingsStyle; Main.Navigate(new YourAutoPage()); }
方案2:在XAML中定义样式,更易维护
把默认样式和选中样式都定义在XAML资源里,这样样式管理更清晰,代码也更简洁。
步骤1:添加样式资源
在窗口的<Window.Resources>里添加:
<!-- 继承Material Design的默认扁平按钮样式 --> <Style x:Key="DefaultMenuButtonStyle" TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}"> <Setter Property="MinWidth" Value="100"/> <!-- 这里可以设置默认的背景/前景,和Material Design保持一致 --> </Style> <!-- 选中状态的样式,基于默认样式修改 --> <Style x:Key="SelectedMenuButtonStyle" TargetType="Button" BasedOn="{StaticResource DefaultMenuButtonStyle}"> <Setter Property="Background" Value="#303030"/> <Setter Property="Foreground" Value="#d50000"/> </Style>
步骤2:给按钮应用默认样式
修改你的按钮XAML:
<StackPanel Orientation="Horizontal" Height="35" VerticalAlignment="Top"> <Button x:Name="User_B" Content="Users" Style="{StaticResource DefaultMenuButtonStyle}" Click="User_B_Click"/> <Button x:Name="Auto_B" Content="Auto" Style="{StaticResource DefaultMenuButtonStyle}" Click="Auto_B_Click"/> <Button x:Name="Clien_B" Content="Client" Style="{StaticResource DefaultMenuButtonStyle}" Click="Clien_B_Click"/> <Button x:Name="Failure_B" Content="Failure" Style="{StaticResource DefaultMenuButtonStyle}" Click="Failure_B_Click"/> <Button x:Name="Settings_B" Content="Settings" Style="{StaticResource DefaultMenuButtonStyle}" Click="Settings_B_Click"/> </StackPanel>
步骤3:简化点击事件代码
现在切换样式只需要直接引用资源即可:
private void User_B_Click(object sender, RoutedEventArgs e) { // 应用选中样式到当前按钮,其他按钮用默认样式 User_B.Style = (Style)FindResource("SelectedMenuButtonStyle"); Auto_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Clien_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Failure_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Settings_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Main.Navigate(new YourUserPage()); } private void Auto_B_Click(object sender, RoutedEventArgs e) { Auto_B.Style = (Style)FindResource("SelectedMenuButtonStyle"); User_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Clien_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Failure_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Settings_B.Style = (Style)FindResource("DefaultMenuButtonStyle"); Main.Navigate(new YourAutoPage()); }
方案3:用ToggleButton实现单选菜单(最优雅)
这种方式利用WPF的ToggleButton和单选组特性,自动管理选中状态,不需要手动重置其他按钮的样式,代码量最少。
步骤1:定义ToggleButton样式
在<Window.Resources>里添加:
<Style x:Key="MenuToggleButtonStyle" TargetType="ToggleButton" BasedOn="{StaticResource MaterialDesignFlatToggleButton}"> <Setter Property="MinWidth" Value="100"/> <!-- 默认状态样式,和Material Design保持一致 --> <Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}"/> <Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}"/> <!-- 选中状态触发器 --> <Style.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter Property="Background" Value="#303030"/> <Setter Property="Foreground" Value="#d50000"/> </Trigger> </Style.Triggers> </Style>
步骤2:替换Button为ToggleButton,并设置GroupName
同一个GroupName的ToggleButton会自动实现单选效果:
<StackPanel Orientation="Horizontal" Height="35" VerticalAlignment="Top"> <ToggleButton x:Name="User_B" Content="Users" Style="{StaticResource MenuToggleButtonStyle}" GroupName="MainMenu" Click="User_B_Click"/> <ToggleButton x:Name="Auto_B" Content="Auto" Style="{StaticResource MenuToggleButtonStyle}" GroupName="MainMenu" Click="Auto_B_Click"/> <ToggleButton x:Name="Clien_B" Content="Client" Style="{StaticResource MenuToggleButtonStyle}" GroupName="MainMenu" Click="Clien_B_Click"/> <ToggleButton x:Name="Failure_B" Content="Failure" Style="{StaticResource MenuToggleButtonStyle}" GroupName="MainMenu" Click="Failure_B_Click"/> <ToggleButton x:Name="Settings_B" Content="Settings" Style="{StaticResource MenuToggleButtonStyle}" GroupName="MainMenu" Click="Settings_B_Click"/> </StackPanel>
步骤3:简化代码,只处理导航
现在不需要管理样式切换,WPF会自动处理选中状态:
private void User_B_Click(object sender, RoutedEventArgs e) { Main.Navigate(new YourUserPage()); } private void Auto_B_Click(object sender, RoutedEventArgs e) { Main.Navigate(new YourAutoPage()); } // 其他按钮的点击事件同理,只需要处理导航逻辑
这样实现的效果完全符合你想要的示例图,而且样式和交互都保留了Material Design的特性,代码也更简洁易维护。
内容的提问来源于stack exchange,提问作者J_Goblin
相关产品推荐
相关产品推荐

