此版本是根据别人的项目改造的,记录下笔记
原文:https://blog.csdn.net/catshitone/article/details/75089069
一、即时弹出
1.创建弹出框
新建一个100*300的WPF页面NotificationWindow.Xaml
<Grid Background="AliceBlue"> <Button Click="Button_Click" Content="Close" HorizontalAlignment="Left" Margin="225,0,0,0" VerticalAlignment="Top" Width="75"/> <TextBlock x:Name="tbTitle" HorizontalAlignment="Left" Margin="31,16,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/> <TextBlock x:Name="tbContent" HorizontalAlignment="Left" Margin="31,42,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/> </Grid>
后置页代码
public partial class NotificationWindow : Window { public double TopFrom { get; set; } public NotificationWindow() { InitializeComponent(); this.Loaded += NotificationWindow_Loaded; } private void NotificationWindow_Loaded(object sender, RoutedEventArgs e) { NotifyData data= this.DataContext as NotifyData; if(data!=null) { tbContent.Text = data.Content; tbTitle.Text = data.Title; } NotificationWindow self = sender as NotificationWindow; if (self != null) { self.UpdateLayout(); SystemSounds.Asterisk.Play();//播放提示声 double right = SystemParameters.WorkArea.Right;//工作区最右边的值 self.Top = self.TopFrom - self.ActualHeight; DoubleAnimation animation = new DoubleAnimation(); animation.Duration = new Duration(TimeSpan.FromMilliseconds(500));//NotifyTimeSpan是自己定义的一个int型变量,用来设置动画的持续时间 animation.From = right; animation.To = right - self.ActualWidth;//设定通知从右往左弹出 self.BeginAnimation(Window.LeftProperty, animation);//设定动画应用于窗体的Left属性 Task.Factory.StartNew(delegate { int seconds = 5;//通知持续5s后消失 System.Threading.Thread.Sleep(TimeSpan.FromSeconds(seconds)); //Invoke到主进程中去执行 this.Dispatcher.Invoke(delegate { animation = new DoubleAnimation(); animation.Duration = new Duration(TimeSpan.FromMilliseconds(500)); animation.Completed += (s, a) => { self.Close(); };//动画执行完毕,关闭当前窗体 animation.From = right - self.ActualWidth; animation.To = right;//通知从左往右收回 self.BeginAnimation(Window.LeftProperty, animation); }); }); } } private void Button_Click(object sender, RoutedEventArgs e) { double right = SystemParameters.WorkArea.Right; DoubleAnimation animation = new DoubleAnimation(); animation.Duration = new Duration(TimeSpan.FromMilliseconds(500)); animation.Completed += (s, a) => { this.Close(); }; animation.From = right - this.ActualWidth; animation.To = right; this.BeginAnimation(Window.LeftProperty, animation); } }
2.弹出消息
在主页面创建一个弹出按钮,事件如下
private void Button_Click(object sender, RoutedEventArgs e) { i++; NotifyData data = new NotifyData(); data.Title = "这是标题:" + i; data.Content = "这是手动内容 "; showNotify(data); } private void showNotify(NotifyData data) { NotificationWindow dialog = new NotificationWindow();//new 一个通知 dialog.Closed += Dialog_Closed; dialog.TopFrom = GetTopFrom(); dialog.DataContext = data;//设置通知里要显示的数据 dialog.Show(); _dialogs.Add(dialog); }
二、定时弹出
1.创建弹出框
和前面的第一步一样
2.创建事件通知接口
部分代码
/// <summary> /// 事件通知接口 /// </summary> public interface IEventNotify { /// <summary> /// 事件通知 /// </summary> void EventNotify(EventData eventData); } /// <summary> /// 事件数据实体 /// </summary> public class EventData { public EventNotifyType EventNotify { get; set; } public object Data { get; set; } }
3.实现定时消息
在消息管理类添加一个定时器,每隔3秒执行一次。
在Timer_Elapsed中,定时获取最新数据
public class NoticeManager : IDisposable { /// <summary> /// 定时器 /// </summary> private readonly Timer _timer; public IMainEventCommnuicationHandler Handler { get; private set; } private int seconds = 1 * 3; public NoticeManager(IMainEventCommnuicationHandler handler) { Handler = handler; _timer = new Timer(seconds * 1000); _timer.Elapsed += Timer_Elapsed; _timer.Start(); } /// <summary> /// 定时事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void Timer_Elapsed(object sender, ElapsedEventArgs e) { for (int i = 0; i < 3; i++) { var notifyData = new NotifyData() { Title = "标题" + i, Content = DateTime.Now.AddHours(i).ToString() }; EventData eventData = new EventData() { EventNotify = EventNotifyType.New, Data = notifyData }; Handler.EventNotify(eventData); } } public void Dispose() { if (_timer != null) { _timer.Stop(); _timer.Dispose(); } } }
4.弹出消息
private NoticeManager noticeManager; private void Time_Click(object sender, RoutedEventArgs e) { if (noticeManager == null) { noticeManager = new NoticeManager(this); btnTime.Content = "暂停弹出"; } else { btnTime.Content = "定时弹出"; noticeManager.Dispose(); } } public void EventNotify(EventData eventData) { if (eventData.EventNotify == EventNotifyType.New) { var data = eventData.Data as NotifyData; SendMessage(data); } else { MessageBox.Show("其他定时消息"); } } /// <summary> /// 发出通知 /// </summary> /// <param name="data"></param> void SendMessage(NotifyData data) { //此处调用Invoke,否则会报错:“ 调用线程必须为 STA,因为许多 UI 组件都需要 ”。 App.Current.Dispatcher.Invoke(() => { showNotify(data); }); }
事件通知时不能直接使用UI组件,否则会报错:“ 调用线程必须为 STA,因为许多 UI 组件都需要 ”。
Dispatcher是一个线程控制器,反正你要控制线程里跑的东西,就要经过它。那么WPF里面,有个所谓UI线程,后台代码不能直接操作UI控件,需要控制,就要通过这个Dispatcher。
参考:https://www.cnblogs.com/xinaixia/p/5706096.html
demo下载:https://gitee.com/zmsofts/XinCunShanNianDaiMa/blob/master/NotificationDemoWPF.rar