You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MaterialDesignInXamlToolkit:如何为不同类型的Snackbar消息设置差异化样式?

这个问题我之前也碰到过,你的初始方案的核心问题在于:SnackBar的样式是绑定到ViewModel的全局属性MessageQueueType,而消息队列里的所有消息都会共享这个属性的值——当你添加新消息时更新这个属性,所有待显示的消息都会跟着用最新的样式,这就是为什么所有消息都变成最后那个类型的样式了。

不用创建多个SnackBar和队列,我们可以让每个消息自己携带样式信息,通过自定义模板实现不同消息的差异化样式,这是更优雅的解决方案:

优化方案:让每个消息携带自身样式标识

1. 创建自定义消息模型

首先定义一个类,把消息内容和状态打包在一起,让每个消息都有自己的类型标识:

public class StyledSnackbarMessage
{
    public string Content { get; set; }
    public MessageQueueStatus Status { get; set; }
}

(假设你的MessageQueueStatus枚举已经包含Error/Info/Success这几个值)

2. 更新ViewModel的消息发送逻辑

修改ShowSnackMessage方法,把自定义的消息对象加入队列,不再依赖全局的MessageQueueType属性:

private void ShowSnackMessage(string message, MessageQueueStatus messageQueueType, bool ClearOtherMessages = false)
{
    if(ClearOtherMessages) MessageQueue.Clear();
    // 将消息内容和状态打包成自定义对象入队
    MessageQueue.Enqueue(new StyledSnackbarMessage
    {
        Content = message,
        Status = messageQueueType
    });
}

3. 自定义SnackBar的消息模板

在XAML中给MainSnackbar设置DataTemplate,让它根据每个消息的Status属性动态应用样式:

<materialDesign:Snackbar x:Name="MainSnackbar" Grid.Row="0" 
                         HorizontalAlignment="Center" 
                         ActionButtonPlacement="Inline"
                         MessageQueue="{Binding MessageQueue}">
    <materialDesign:Snackbar.DataTemplate>
        <DataTemplate DataType="{x:Type local:StyledSnackbarMessage}">
            <Border x:Name="SnackbarContainer" Padding="16" CornerRadius="4">
                <TextBlock Text="{Binding Content}" 
                           Foreground="{Binding Status, Converter={StaticResource StatusToMessageForegroundColorConverter}}"/>
            </Border>
            <DataTemplate.Triggers>
                <!-- 根据消息状态设置背景色 -->
                <DataTrigger Binding="{Binding Status}" Value="Error">
                    <Setter TargetName="SnackbarContainer" Property="Background" Value="#8B0000"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Status}" Value="Info">
                    <Setter TargetName="SnackbarContainer" Property="Background" Value="#696969"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Status}" Value="Success">
                    <Setter TargetName="SnackbarContainer" Property="Background" Value="#228B22"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </materialDesign:Snackbar.DataTemplate>
</materialDesign:Snackbar>

如果你想继续使用之前的转换器,也可以直接把Border的Background绑定到Status:

<Border Background="{Binding Status, Converter={StaticResource StatusToMessageBackgroundColorConverter}}" ...>

4. 移除全局样式绑定

记得删掉原来SnackBar上的Background和Foreground绑定,现在样式由每个消息的模板独立控制,不再依赖ViewModel的全局属性。

这样修改后,每个消息都会根据自身携带的Status显示对应的样式,不管队列里有多少不同类型的消息,都能正确渲染各自的样式,而且只需要一个SnackBar和一个队列,比多实例方案简洁得多。

内容的提问来源于stack exchange,提问作者Rafael Leonardi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:32:42