此版本是根據別人的項目改造的,記錄下筆記html
原文:https://blog.csdn.net/catshitone/article/details/75089069git
新建一個100*300的WPF頁面NotificationWindow.Xamlapp
<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>
後置頁代碼async
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); } }
在主頁面建立一個彈出按鈕,事件以下動畫
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); }
和前面的第一步同樣ui
部分代碼this
/// <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秒執行一次。spa
在Timer_Elapsed中,定時獲取最新數據.net
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(); } } }
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。
參考:http://www.javashuo.com/article/p-ogyiubeh-ck.html
demo下載:https://gitee.com/zmsofts/XinCunShanNianDaiMa/blob/master/NotificationDemoWPF.rar