一、概要
原版的消息框太丑?不喜欢?如果您对原版消息框的外观不太满意,或者不符合您的应用程序的需求,那么可以通过自定义消息框来实现所需的外观和功能。
原版的消息框:可以看出这个消息框可能和你设计的UI界面格格不入
自定义消息框可以实现各种风格和布局的效果。
下面我展示一个B端设计的消息框界面
那么我们如何做到类似的效果呢?
- 构思背景遮罩逻辑
- 制作UI界面(遮罩+Popup)
- Cs后端弹窗实现(Await)
实现效果展示:
其中,按钮颜色、文本,图标等都可以通过自定义。
快速通道:下载链接
二、UI制作流程
下面我们一步一步制作这个弹窗。
1.遮罩逻辑
首先是背景层:
背景层是一个半透明的遮罩蒙版。
<Grid x:Name="MessageGridBox" Visibility="Collapsed">
<Border Background="White" Opacity="0.8" CornerRadius="5"/>
<!--这里放消息框的部分--!/>
<!--这里放消息框的部分--!/>
</Grid>
效果就是一块蒙版挡住用户其他使用区域。(当然你也可以选择不挡着或者设计逻辑选择性挡住或者不挡住,挡住的话可以防止用户不处理这个消息就去其他操作。)
这里的CornerRadius="5"
可以改为自己的主界面的圆角,当然也可以不设置。
2.Popup展示层
中间层是Popup展示层:
为了让消息框弹出不那么突兀,使用了Popup
的Fade
展示效果显示。
<Popup x:Name="MessageGridPopup" PopupAnimation="Fade" Placement="Center" AllowsTransparency="True" StaysOpen="True">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="450" MaxHeight="250" MinWidth="400" MinHeight="165">
<Grid.RowDefinitions>
<RowDefinition Height="55"/>
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Grid.RowSpan="2" Fill="White" Margin="5" Opacity="1" RadiusY="5" RadiusX="5">
<Rectangle.Effect>
<DropShadowEffect Color="#FFBBBBBB" Direction="0" BlurRadius="10" RenderingBias="Quality" ShadowDepth="0" Opacity="0.3"></DropShadowEffect>
</Rectangle.Effect>
</Rectangle>
<!--这里放消息展示内容部分--!/>
<!--这里放消息展示内容部分--!/>
</Grid>
</Popup>
3.消息展示层
消息展示层是核心区域,用于动态更新消息框的展示文本。
我分三个部分来介绍:
- 标题部分
<Grid Margin="10,0,10,0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="10,0,0,0">
<TextBlock x:Name="MessageIconQ" Text="" FontFamily="{DynamicResource Iconfont}" FontSize="22" VerticalAlignment="Center" Margin="10"/>
<TextBlock x:Name="MessageIconC" Text="" FontFamily="{DynamicResource Iconfont}" FontSize="22" VerticalAlignment="Center" Margin="10" Visibility="Collapsed"/>
<TextBlock x:Name="MessageTitleBox" Text="标题显示" FontFamily="{DynamicResource BlodFont}" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
<Button HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,20,10" FontSize="22" Style="{DynamicResource wdButton}" Click="CancelBtn_Click">
<Button.Content>
<TextBlock FontFamily="{DynamicResource Iconfont}" Text=""/>
</Button.Content>
</Button>
</Grid>
- 内容区域
<StackPanel Grid.RowSpan="2" Margin="10">
<TextBlock x:Name="MessageContentBox" Margin="50,60,50,80" TextWrapping="Wrap" Text="消息框测试" FontSize="14" FontFamily="{DynamicResource RegularFont}"/>
</StackPanel>
- 按钮部分
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10" >
<Button x:Name="CancelBtn" Content="取消" Style="{DynamicResource wButton}" Width="100" FontSize="15" Height="35" Margin="10" Click="CancelBtn_Click"/>
<Button x:Name="ConfirmBtn" Content="确定" Style="{DynamicResource mButton}" Width="100" FontSize="15" Height="35" Margin="10" Click="ConfirmBtn_Click"/>
</StackPanel>
按钮还可以继续增加,逻辑我就不赘述了,可以看后面的代码研究一下。
值得注意的是:这里的
Style
是我自己做的,你也可以更换为自己的按钮样式,如果有需要可以后台私信我。除了底层逻辑,这些样式都可以自己自定义。
三、C#后端代码逻辑
1. 定义变量
首先定义一个TaskCompletionSource<bool>
命名taskCompletionSource
,当然名字可以自己改。
private TaskCompletionSource<bool> taskCompletionSource;
#这段内容需要全局变量哦
2. 定义函数
写一个显示消息框的函数,注意函数需要async
才支持等待用户回复。
private async Task<bool> ShowMessageGridBoxAsync(string MessageContent,string title,bool isconfirm = true, int ButtonIndex=0)
{
/// <summary>
/// 参数分别是
/// MessageContent 信息内容
/// title 信息标题
/// isconfirm 是否确认按钮(判断Icon情况)
/// ButtonIndex 按钮类型
/// </summary>
//#我这里的后两个参数带默认值,所以可以直接简化写。
//#展示消息框
MessageGridBox.Visibility = Visibility.Visible;
MessageTitleBox.Text = title;
MessageContentBox.Text = MessageContent;
//#上面这些比较简单就不赘述了。分别赋值进去。
//#重新赋值一个 taskCompletionSource 让其重置。
taskCompletionSource = new TaskCompletionSource<bool>();
//#判断ICON 其中MessageIconC是确认的ICON,MessageIconQ是询问的ICON
if (isconfirm)
{
CancelBtn.Visibility = Visibility.Collapsed;
MessageIconC.Visibility = Visibility.Visible;
MessageIconQ.Visibility = Visibility.Collapsed;
}
else
{
CancelBtn.Visibility = Visibility.Visible;
MessageIconC.Visibility = Visibility.Collapsed;
MessageIconQ.Visibility = Visibility.Visible;
}
//#判断按钮的类型
switch (ButtonIndex)
{
case 0:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["mButton"]);
ConfirmBtn.Content = "确认";
break;
case 1:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "删除";
System.Media.SystemSounds.Exclamation.Play();
break;
case 2:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "确认";
System.Media.SystemSounds.Exclamation.Play();
break;
case 3:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "重试";
System.Media.SystemSounds.Exclamation.Play();
break;
case 4:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["mButton"]);
ConfirmBtn.Content = "我知道了";
break;
}
//#这里写了4个类型,你可以再自定义更多
//#这里要先关闭再打开!不然动态效果就没了。
MessageGridPopup.IsOpen = false;
MessageGridPopup.IsOpen = true;
//#等待Task用户操作
await taskCompletionSource.Task;
//#操作后隐藏遮罩与Popup
MessageGridBox.Visibility = Visibility.Collapsed;
MessageGridPopup.IsOpen = false;
//#返回Task的Result
return taskCompletionSource.Task.Result;
}
3.写按钮按下的逻辑
private void ConfirmBtn_Click(object sender, RoutedEventArgs e)
{
// 设置任务结果为true,并标记任务为已完成
taskCompletionSource.SetResult(true);
}
private void CancelBtn_Click(object sender, RoutedEventArgs e)
{
// 设置任务结果为false,并标记任务为已完成
taskCompletionSource.SetResult(false);
}
4.如何调用这个函数
确认框情况
ShowMessageGridBoxAsync("-欢迎使用-", "欢迎:");
需要判断的情况
bool result = await ShowMessageGridBoxAsync("寻找不到该文件,是否删除?", "错误:", false, 1);
//这里的1是删除按钮哦,可以看前面的定义
四、技术细节/常见错误
- 消息框初始化需要关闭状态。不然会出错哦
- Popup的
StaysOpen="True"
,不然点击其他地方就自动关闭了,然后就会剩下遮罩无法操作 - Popup和Grid都需要在用户操作完后隐藏!
- 在调用需要await的情况,所在函数需要支持
async
才可以,“await”运算符只能用于异步方法中。请考虑用“async"修饰符标记此方法。
举个例子:
private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{
bool result = await ShowMessageGridBoxAsync("点击删除后记录将被删除,该操作不可逆。", "确认要删除这条记录么?", false, 1);
if (result)
{
//按钮逻辑
}
}
五、小结/完整代码
Xml部分
<Grid x:Name="MessageGridBox" Visibility="Collapsed">
<Border Background="White" Opacity="0.8" CornerRadius="5"/>
<Popup x:Name="MessageGridPopup" PopupAnimation="Fade" Placement="Center" AllowsTransparency="True" StaysOpen="True">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="450" MaxHeight="250" MinWidth="400" MinHeight="165">
<Grid.RowDefinitions>
<RowDefinition Height="55"/>
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Grid.RowSpan="2" Fill="White" Margin="5" Opacity="1" RadiusY="5" RadiusX="5">
<Rectangle.Effect>
<DropShadowEffect Color="#FFBBBBBB" Direction="0" BlurRadius="10" RenderingBias="Quality" ShadowDepth="0" Opacity="0.3"></DropShadowEffect>
</Rectangle.Effect>
</Rectangle>
<Grid Margin="10,0,10,0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="10,0,0,0">
<TextBlock x:Name="MessageIconQ" Text="" FontFamily="{DynamicResource Iconfont}" FontSize="22" VerticalAlignment="Center" Margin="10"/>
<TextBlock x:Name="MessageIconC" Text="" FontFamily="{DynamicResource Iconfont}" FontSize="22" VerticalAlignment="Center" Margin="10" Visibility="Collapsed"/>
<TextBlock x:Name="MessageTitleBox" d:Text="标题显示" FontFamily="{DynamicResource BlodFont}" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
<Button HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,20,10" FontSize="22" Style="{DynamicResource wdButton}" Click="CancelBtn_Click">
<Button.Content>
<TextBlock FontFamily="{DynamicResource Iconfont}" Text=""/>
</Button.Content>
</Button>
</Grid>
<StackPanel Grid.RowSpan="2" Margin="10">
<TextBlock x:Name="MessageContentBox" Margin="50,60,50,80" TextWrapping="Wrap" Text="消息框测试" FontSize="14" FontFamily="{DynamicResource RegularFont}"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10" >
<Button x:Name="CancelBtn" Content="取消" Style="{DynamicResource wButton}" Width="100" FontSize="15" Height="35" Margin="10" Click="CancelBtn_Click"/>
<Button x:Name="ConfirmBtn" Content="确定" Style="{DynamicResource mButton}" Width="100" FontSize="15" Height="35" Margin="10" Click="ConfirmBtn_Click"/>
</StackPanel>
</Grid>
</Popup>
</Grid>
C#部分
文章来源:https://www.toymoban.com/news/detail-768859.html
namespace Pro
{
public partial class MainWindow : Window
{
private TaskCompletionSource<bool> taskCompletionSource;
/// <summary>
/// 参数分别是
/// MessageContent 信息内容
/// title 信息标题
/// isconfirm 是否确认按钮(判断Icon情况)
/// ButtonIndex 按钮类型
/// </summary>
private async Task<bool> ShowMessageGridBoxAsync(string MessageContent,string title,bool isconfirm = false, int ButtonIndex=0)
{
//#我这里的后两个参数带默认值,所以可以直接简化写。
//#展示消息框
MessageGridBox.Visibility = Visibility.Visible;
MessageTitleBox.Text = title;
MessageContentBox.Text = MessageContent;
//#上面这些比较简单就不赘述了。分别赋值进去。
//#重新赋值一个 taskCompletionSource 让其重置。
taskCompletionSource = new TaskCompletionSource<bool>();
//#判断ICON 其中MessageIconC是确认的ICON,MessageIconQ是询问的ICON
if (isconfirm)
{
CancelBtn.Visibility = Visibility.Collapsed;
MessageIconC.Visibility = Visibility.Visible;
MessageIconQ.Visibility = Visibility.Collapsed;
}
else
{
CancelBtn.Visibility = Visibility.Visible;
MessageIconC.Visibility = Visibility.Collapsed;
MessageIconQ.Visibility = Visibility.Visible;
}
//#判断按钮的类型
switch (ButtonIndex)
{
case 0:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["mButton"]);
ConfirmBtn.Content = "确认";
break;
case 1:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "删除";
System.Media.SystemSounds.Exclamation.Play();
break;
case 2:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "确认";
System.Media.SystemSounds.Exclamation.Play();
break;
case 3:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["RButton"]);
ConfirmBtn.Content = "重试";
System.Media.SystemSounds.Exclamation.Play();
break;
case 4:
ConfirmBtn.SetValue(Button.StyleProperty, Application.Current.Resources["mButton"]);
ConfirmBtn.Content = "我知道了";
break;
}
//#这里写了4个类型,你可以再自定义更多
//#这里要先关闭再打开!不然动态效果就没了。
MessageGridPopup.IsOpen = false;
MessageGridPopup.IsOpen = true;
//#等待Task用户操作
await taskCompletionSource.Task;
//#操作后隐藏遮罩与Popup
MessageGridBox.Visibility = Visibility.Collapsed;
MessageGridPopup.IsOpen = false;
//#返回Task的Result
return taskCompletionSource.Task.Result;
}
private void ConfirmBtn_Click(object sender, RoutedEventArgs e)
{
// 设置任务结果为true,并标记任务为已完成
taskCompletionSource.SetResult(true);
}
private void CancelBtn_Click(object sender, RoutedEventArgs e)
{
// 设置任务结果为false,并标记任务为已完成
taskCompletionSource.SetResult(false);
}
private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{
bool result = await ShowMessageGridBoxAsync("点击删除后记录将被删除,该操作不可逆。", "确认要删除这条记录么?", false, 1);
if (result)
{
ShowMessageGridBoxAsync("-你点击了删除-", "提示:");
}else
{
ShowMessageGridBoxAsync("-你点击了取消-", "提示:");
}
}
}
}
感谢观看,代码还有需要完善的地方,欢迎指正。文章来源地址https://www.toymoban.com/news/detail-768859.html
到了这里,关于【WPF】消息蒙版弹窗UI以及await实现等待反馈(popup)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!