How to change the style (eg background/foreground colors) for different messages? I want to show Sucess, Info and Error messages with different styles.
I tried using bindings with a converter like this:
XAML:
<materialDesign:Snackbar
x:Name="MainSnackbar"
Grid.Row="0"
HorizontalAlignment="Center"
ActionButtonPlacement="Inline"
Background="{Binding MessageQueueType, Converter={StaticResource StatusToMessageBackgroundColorConverter}, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding MessageQueueType, Converter={StaticResource StatusToMessageForegroundColorConverter}, UpdateSourceTrigger=PropertyChanged}"
MessageQueue="{Binding MessageQueue}" />
Converter C#:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch ((MessageQueueStatus)value)
{
case MessageQueueStatus.Error:
return new SolidColorBrush(Colors.DarkRed);
case MessageQueueStatus.Info:
return new SolidColorBrush(Colors.DimGray);
case MessageQueueStatus.Sucess:
return new SolidColorBrush(Colors.ForestGreen);
}
return null;
}
VM C#:
private void ShowSnackMessage(string message, MessageQueueStatus messageQueueType, bool ClearOtherMessages = false)
{
if(ClearOtherMessages)
MessageQueue.Clear();
MessageQueueType = messageQueueType;
MessageQueue.Enqueue(message);
}
But the if I queue more than 1 type of message at a time, only the last selected 'style' is applied. If I queue first an 'Info' message than a 'Success' message, both will show as 'Sucess style'.
I achieved what I want creating 3 different Snackbars directly in XAML with different styles set and 3 different MessageQueues in VM. But this way I need to create a different object and queue for each style I need. Is this the only way to do it?
We made a trick to have this behaviour without having the need of multiple snack bars.
The idea is to keep the list of enqueued messages in the snackbar in a separate list and when a message is removed from the snack bar (just before putting the next one) we change the background color of the snackbar with a trigger on a property containing the info to choose the color.
Our snackbar in xaml
<materialDesign:Snackbar Name="MainSnackbar" ActionButtonStyle="{StaticResource SnackActionButton}" Grid.Row="2" Grid.ColumnSpan="2" MessageQueue="{Binding MessageQueue}" Message="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center">
<utilities:TreeHelpers.Modifiers>
<utilities:ModifierCollection >
<utilities:Modifier TemplatePartName="ContentBorder" Property="{x:Static Border.CornerRadiusProperty}" Value="20 20 0 0">
</utilities:Modifier>
</utilities:ModifierCollection>
</utilities:TreeHelpers.Modifiers>
<materialDesign:Snackbar.Style>
<Style TargetType="materialDesign:Snackbar" BasedOn="{StaticResource {x:Type materialDesign:Snackbar}}">
<Setter Property="Background" Value="{StaticResource MaterialDesignSnackbarBackground}"></Setter>
<Setter Property="MaxWidth" Value="{Binding ActualWidth, ElementName=AppGrid}" />
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentMessageLevel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="1">
<Setter Property="Background" Value="{StaticResource FwBrushError}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentMessageLevel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="2">
<Setter Property="Background" Value="{StaticResource FwBrushWarning}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentMessageLevel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="3">
<Setter Property="Background" Value="{StaticResource FwBrushInfo}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentMessageLevel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="4">
<Setter Property="Background" Value="{StaticResource FwBrushSuccess}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</materialDesign:Snackbar.Style>
</materialDesign:Snackbar>
The part where we enqueue messages
public class MessageToSnack
{
public string Content { get; set; } = "";
public MessageToSnackLevel Level { get; set; } = 0;
public TimeSpan? Duration { get; set; } = null; // if null it will use the default duration of material design -> 3s
public bool WithCloseButton { get; set; } = true;
}
public enum MessageToSnackLevel
{
NoLevel = 0,
Error = 1,
Warning = 2,
Info = 3,
Success = 4,
}
private void EventSnackMessageReceived(MessageToSnack snakMsg)
{
_snackedMessages.Add(snakMsg);
if (snakMsg.WithCloseButton)
{
MessageQueue.Enqueue(snakMsg.Content, new PackIcon() { Kind = PackIconKind.Close}, (queue) => CloseCommand(queue), MessageQueue, false, false, snakMsg.Duration);
}
else
{
MessageQueue.Enqueue(snakMsg.Content, null, null, null, false, false, snakMsg.Duration);
}
}
The part to manage the CurrenMessageLevel property
List<MessageToSnack> _snackedMessages = new List<MessageToSnack>(); // used when intercepting a snackbar message poping , to find its reference and be able to change the color with a trigger on the CurrentLevel
private SnackbarMessage _message;
public SnackbarMessage Message
{
get { return _message; }
set
{
SetProperty(ref _message, value);
if (_message != null)
{
var localMessage = _snackedMessages.FirstOrDefault(m => m.Content.Equals(_message.Content.ToString()));
if (localMessage != null)
{
CurrentMessageLevel = localMessage.Level;
_snackedMessages.Remove(localMessage);
}
else
{
CurrentMessageLevel = 0;
}
}
else
{
CurrentMessageLevel = 0;
}
}
}
private MessageToSnackLevel _currentMessageLevel;
public MessageToSnackLevel CurrentMessageLevel
{
get { return _currentMessageLevel; }
set { SetProperty(ref _currentMessageLevel, value); }
}