1. Overview
This article explains how to implement a message center feature based on WPF. For example, in common software, you often receive messages such as "news" or "announcements" pushed from the server. In this case, an analysis of this requirement is needed.
Functional analysis is as follows:
- Display message content.
- Add, delete, and batch delete messages.
- Message classification (notification messages, interactive messages such as those that can jump to a certain link or module within the program).
- Message handling (accept, delete, ignore).
2. Implementation

- Display message content
Here, the custom control is considered a ListBox. The messages themselves are multiple items, and each item needs to be operated on.
<ListBox
Grid.Row="1"
MaxHeight="335"
Background="{x:Null}"
BorderThickness="0"
ItemContainerStyle="{DynamicResource ListBoxItemStyle}"
ItemsSource="{Binding MessageItem}"
ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type localModel:MessageItemModel}">
<Border
Height="30"
BorderBrush="#FFBDBDBD"
BorderThickness="0,0,0,0.6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<DockPanel>
<Label
MaxWidth="70"
Content="{Binding Path=Name}"
Foreground="Red"
ToolTip="{Binding Path=Name}" />
<Label
MaxWidth="130"
Content="{Binding Path=Content}"
Foreground="White"
ToolTip="{Binding Path=Content}" />
</DockPanel>
<CheckBox
Grid.Column="1"
FlowDirection="RightToLeft"
IsChecked="{Binding Path=CheckBoxState}" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Add, delete, and batch delete messages
Once the main container is determined, the next step is to customize each message as a ListBoxItem, with specific handling for each message.
For example:
- Notification messages: only need a confirm button.
- Interactive messages: need confirm, delete, and ignore buttons.
<DataTemplate x:Key="SelectedTemplate" DataType="{x:Type localModel:MessageItemModel}">
<Border BorderBrush="#FFBDBDBD" BorderThickness="0,0,0,0.6">
<StackPanel>
<TextBox
MaxWidth="240"
MaxHeight="200"
Padding="0,5,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
BorderThickness="0"
FontSize="14"
Foreground="White"
IsReadOnly="True"
Text="{Binding Path=Content}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Path=Content}"
VerticalScrollBarVisibility="Auto" />
<StackPanel
Margin="5,5,5,9"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Button
Width="60"
Height="25"
Margin="5"
Command="{Binding DataContext.ClickAcceptCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"
Content="Accept"
Style="{StaticResource BlueButtonStyle}"
Visibility="{Binding Path=InvitationType, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button
Width="60"
Height="25"
Margin="5"
Command="{Binding DataContext.ClickRefuseCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"
Content="Ignore"
Style="{StaticResource BlueButtonStyle}"
Visibility="{Binding Path=InvitationType, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button
Width="60"
Height="25"
Margin="5"
Command="{Binding DataContext.ClickAgreeCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"
Content="Confirm"
Style="{StaticResource BlueButtonStyle}"
Visibility="{Binding Path=NoticeType, Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
Message classification
Here, it is sufficient to define specific enumerations in the Model layer.
/// <summary>
/// Message processing result
/// </summary>
public enum SysMessageResult
{
/// <summary>
/// Unhandled
/// </summary>
Unhandled = 0,
/// <summary>
/// Processed
/// </summary>
Processed = 1
}
/// <summary>
/// Message type
/// </summary>
public enum SysMessageType
{
/// <summary>
/// Notification type
/// </summary>
NoticeType = 0,
/// <summary>
/// Other type
/// </summary>
OtherType = 1
}
Message handling
Message handling refers to the logic for processing message content using the three buttons: "Confirm", "Accept", and "Ignore". If needed, you can modify these according to your requirements. My definition here is as follows:
- Confirm: Usually handles notification messages. Processing simply removes the item from the message list and does nothing else.
- Accept: Handles interactive type buttons. Processing removes the item from the message list and triggers other business processing actions.
- Ignore: Handles all types of messages. It only does not display the message in the UI, but it still exists in the message list, to be processed later when idle.