因系统功能需要,需要那种像微信一样的Toast弹出框,可以有图标和文字提示,然后一定时间后可以自动消失
本文章主要讲如何通过自定义控件配合Popup实现个性化Toast提示框,使用Net4开发,支持XP。目前主要实现了如下几个功能:
TopLeft-------TopCenter------TopRight
| | |
CenterLeft-----Center-----CenterRight
| | |
BottomLeft--BottomCenter--BottomRight
TopLeft-------TopCenter------TopRight
| | |
CenterLeft-----Center-----CenterRight
| | |
BottomLeft--BottomCenter--BottomRight
================任务栏================
Toast使用了Awesome
字体图标库,可以通过以下命令实现安装:
Install-Package MahApps.Metro.IconPacks.FontAwesome -Version 2.3.0
<UserControl x:Class="WpfToast.Controls.Toast"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfToast.Controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
mc:Ignorable="d" Height="{Binding Height}" Width="{Binding Width}" MouseLeftButtonDown="UserControl_MouseLeftButtonDown"
d:DesignHeight="48" d:DesignWidth="200" MinWidth="200" MaxWidth="500" Focusable="False">
<UserControl.Resources>
<local:ToastIconConverter x:Key="icon_converter">local:ToastIconConverter>
UserControl.Resources>
<Border CornerRadius="{Binding CornerRadius}"
BorderThickness="{Binding BorderThickness}"
Background="{Binding Background}"
BorderBrush="{Binding BorderBrush}">
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto">ColumnDefinition>
<ColumnDefinition Width="*">ColumnDefinition>
Grid.ColumnDefinitions>
<iconPacks:PackIconFontAwesome x:Name="icon_toast" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"
Width="{Binding IconSize}" Height="{Binding IconSize}" Margin="10 0 10 0">
<iconPacks:PackIconFontAwesome.Kind>
<MultiBinding Converter="{StaticResource icon_converter}">
<Binding Path="Icon"/>
<Binding ElementName="grid"/>
<Binding ElementName="txt_toast"/>
MultiBinding>
iconPacks:PackIconFontAwesome.Kind>
iconPacks:PackIconFontAwesome>
<TextBlock x:Name="txt_toast" Grid.Column="1" Text="{Binding Message}"
Foreground="{Binding Foreground}"
FontStyle="{Binding FontStyle}"
FontStretch="{Binding FontStretch}"
FontSize="{Binding FontSize}"
FontFamily="{Binding FontFamily}"
FontWeight="{Binding FontWeight}"
VerticalAlignment="{Binding VerticalContentAlignment}"
HorizontalAlignment="{Binding HorizontalContentAlignment}" Padding="0 0 4 0">
TextBlock>
Grid>
Border>
UserControl>
public class ToastOptions
{
public double Width { get; set; } = 200;
public double Height { get; set; } = 48;
public int Time { get; set; } = 2000;
public ToastIcons Icon { get; set; } = ToastIcons.None;
public ToastLocation Location { get; set; } = ToastLocation.Default;
public Brush Foreground { get; set; } = Brushes.White;
public FontStyle FontStyle { get; set; } = SystemFonts.MessageFontStyle;
public FontStretch FontStretch { get; set; } = FontStretches.Normal;
public double FontSize { get; set; } = SystemFonts.MessageFontSize;
public FontFamily FontFamily { get; set; } = SystemFonts.MessageFontFamily;
public FontWeight FontWeight { get; set; } = SystemFonts.MenuFontWeight;
public double IconSize { get; set; } = 26;
public CornerRadius CornerRadius { get; set; } = new CornerRadius(5);
public Brush BorderBrush { get; set; }
public Thickness BorderThickness { get; set; } = new Thickness(1);
public Brush Background { get; set; } = (Brush)new BrushConverter().ConvertFromString("#2E2929");
public HorizontalAlignment HorizontalContentAlignment { get; set; } = HorizontalAlignment.Left;
public VerticalAlignment VerticalContentAlignment { get; set; } = VerticalAlignment.Center;
public EventHandler<EventArgs> Closed { get; internal set; }
public EventHandler<EventArgs> Click { get; internal set; }
}
public enum ToastIcons
{
None,
Information,//CheckSolid
Error,//TimesSolid
Warning,//ExclamationSolid
Busy//ClockSolid
}
public enum ToastLocation
{
OwnerCenter,
OwnerLeft,
OwnerRight,
OwnerTopLeft,
OwnerTopCenter,
OwnerTopRight,
OwnerBottomLeft,
OwnerBottomCenter,
OwnerBottomRight,
ScreenCenter,
ScreenLeft,
ScreenRight,
ScreenTopLeft,
ScreenTopCenter,
ScreenTopRight,
ScreenBottomLeft,
ScreenBottomCenter,
ScreenBottomRight,
Default//OwnerCenter
}
public class ToastIconConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
object value = values[0];
object grid = values[1];
object txt = values[2];
Grid _grid = grid as Grid;
TextBlock _txt = txt as TextBlock;
if (value == null)
{
if (_grid != null)
{
_grid.ColumnDefinitions.RemoveAt(0);
}
if (_txt != null)
{
_txt.HorizontalAlignment = HorizontalAlignment.Center;
}
return PackIconFontAwesomeKind.None;
}
ToastIcons _value;
try
{
_value = (ToastIcons)value;
}
catch
{
if (_grid != null)
{
_grid.ColumnDefinitions.RemoveAt(0);
}
if (_txt != null)
{
_txt.HorizontalAlignment = HorizontalAlignment.Center;
}
return PackIconFontAwesomeKind.None;
}
switch (_value)
{
case ToastIcons.Information:
return PackIconFontAwesomeKind.CheckSolid;
case ToastIcons.Error:
return PackIconFontAwesomeKind.TimesSolid;
case ToastIcons.Warning:
return PackIconFontAwesomeKind.ExclamationSolid;
case ToastIcons.Busy:
return PackIconFontAwesomeKind.ClockSolid;
}
if (_grid != null)
{
_grid.ColumnDefinitions.RemoveAt(0);
}
if (_txt != null)
{
_txt.HorizontalAlignment = HorizontalAlignment.Center;
}
return PackIconFontAwesomeKind.None;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
private Toast()
{
InitializeComponent();
this.DataContext = this;
}
private Toast(Window owner, string message, ToastOptions options = null)
{
Message = message;
InitializeComponent();
if (options != null)
{
Width = options.Width;
Height = options.Height;
Icon = options.Icon;
Location = options.Location;
Time = options.Time;
Closed += options.Closed;
Click += options.Click;
Background = options.Background;
Foreground = options.Foreground;
FontStyle = options.FontStyle;
FontStretch = options.FontStretch;
FontSize = options.FontSize;
FontFamily = options.FontFamily;
FontWeight = options.FontWeight;
IconSize = options.IconSize;
BorderBrush = options.BorderBrush;
BorderThickness = options.BorderThickness;
HorizontalContentAlignment = options.HorizontalContentAlignment;
VerticalContentAlignment = options.VerticalContentAlignment;
CornerRadius = options.CornerRadius;
}
this.DataContext = this;
if (owner == null)
{
this.owner = Application.Current.MainWindow;
}
else
{
this.owner = owner;
}
this.owner.Closed += Owner_Closed;
}
private void Owner_Closed(object sender, EventArgs e)
{
this.Close();
}
private event EventHandler<EventArgs> Closed;
private void RaiseClosed(EventArgs e)
{
Closed?.Invoke(this, e);
}
private event EventHandler<EventArgs> Click;
private void RaiseClick(EventArgs e)
{
Click?.Invoke(this, e);
}
private string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
private static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(string), typeof(Toast), new PropertyMetadata(string.Empty));
private CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
private static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Toast), new PropertyMetadata(new CornerRadius(5)));
private double IconSize
{
get { return (double)GetValue(IconSizeProperty); }
set { SetValue(IconSizeProperty, value); }
}
private static readonly DependencyProperty IconSizeProperty =
DependencyProperty.Register("IconSize", typeof(double), typeof(Toast), new PropertyMetadata(26.0));
private new Brush BorderBrush
{
get { return (Brush)GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
}
private static new readonly DependencyProperty BorderBrushProperty =
DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(Toast), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#FFFFFF")));
private new Thickness BorderThickness
{
get { return (Thickness)GetValue(BorderThicknessProperty); }
set { SetValue(BorderThicknessProperty, value); }
}
private static new readonly DependencyProperty BorderThicknessProperty =
DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(Toast), new PropertyMetadata(new Thickness(0)));
private new Brush Background
{
get { return (Brush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
private static new readonly DependencyProperty BackgroundProperty =
DependencyProperty.Register("Background", typeof(Brush), typeof(Toast), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#2E2929")));
private new HorizontalAlignment HorizontalContentAlignment
{
get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); }
set { SetValue(HorizontalContentAlignmentProperty, value); }
}
private static new readonly DependencyProperty HorizontalContentAlignmentProperty =
DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(Toast), new PropertyMetadata(HorizontalAlignment.Left));
private new VerticalAlignment VerticalContentAlignment
{
get { return (VerticalAlignment)GetValue(VerticalContentAlignmentProperty); }
set { SetValue(VerticalContentAlignmentProperty, value); }
}
private static new readonly DependencyProperty VerticalContentAlignmentProperty =
DependencyProperty.Register("VerticalContentAlignment", typeof(VerticalAlignment), typeof(Toast), new PropertyMetadata(VerticalAlignment.Center));
private new double Width
{
get { return (double)GetValue(WidthProperty); }
set { SetValue(WidthProperty, value); }
}
private new static readonly DependencyProperty WidthProperty =
DependencyProperty.Register("Width", typeof(double), typeof(Toast), new PropertyMetadata(200.0));
private new double Height
{
get { return (double)GetValue(HeightProperty); }
set { SetValue(HeightProperty, value); }
}
private new static readonly DependencyProperty HeightProperty =
DependencyProperty.Register("Height", typeof(double), typeof(Toast), new PropertyMetadata(48.0));
private ToastIcons Icon
{
get { return (ToastIcons)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
private static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(ToastIcons), typeof(Toast), new PropertyMetadata(ToastIcons.None));
private int Time
{
get { return (int)GetValue(TimeProperty); }
set { SetValue(TimeProperty, value); }
}
private static readonly DependencyProperty TimeProperty =
DependencyProperty.Register("Time", typeof(int), typeof(Toast), new PropertyMetadata(2000));
private ToastLocation Location
{
get { return (ToastLocation)GetValue(LocationProperty); }
set { SetValue(LocationProperty, value); }
}
private static readonly DependencyProperty LocationProperty =
DependencyProperty.Register("Location", typeof(ToastLocation), typeof(Toast), new PropertyMetadata(ToastLocation.Default));
public static void Show(string msg, ToastOptions options = null)
{
var toast = new Toast(null, msg, options);
int time = toast.Time;
ShowToast(toast, time);
}
public static void Show(Window owner, string msg, ToastOptions options = null)
{
var toast = new Toast(owner, msg, options);
int time = toast.Time;
ShowToast(toast, time);
}
public void Close()
{
if (timer != null)
{
timer.Stop();
timer = null;
}
popup.IsOpen = false;
owner.LocationChanged -= UpdatePosition;
owner.SizeChanged -= UpdatePosition;
}
private void UpdatePosition(object sender, EventArgs e)
{
var up = typeof(Popup).GetMethod("UpdatePosition", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (up == null || popup == null)
{
return;
}
SetPopupOffset(popup, this);
up.Invoke(popup, null);
}
中间有个消失的,是我用鼠标点击了,实现单击事件和关闭事件
再给你们来个那种某些装逼人士
的任务栏
XP环境下底部始终有一个高度,暂不清楚是不是系统自身原因,win10无此BUG
伸手党:下载地址