此版本是根據別人的項目改造的,記錄下筆記
原文: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