using HistoryDLL.Json; using MediaViewerLib.Utilities; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace HistoryDLL { /// /// CyclicScroller.xaml 的互動邏輯 /// public partial class CyclicScroller : UserControl { public enum HistoryControlMode { Boot = 0x001, Manual = 0x010, AutoRun = 0x100, }; public enum TouchorManipulation { TouchEvent = 0x01, ManipulationEvent = 0x10, }; public enum MonitorFlag { Monitor1_1 = 0x000001, Monitor2_1 = 0x000010, Monitor3_1 = 0x000100, Monitor4_1 = 0x001000, Monitor5_1 = 0x010000, Monitor6_1 = 0x100000, }; public enum StoryBoardStatus { StoryBoardIsRun = 0x01, StoryBoardIsStop = 0x10, }; public delegate void HomeBackInforDelegate(); public event HomeBackInforDelegate HomeBackInforEvent; public event EventHandler OnDataLoadCompeleted; //創造 LiveContainer 物件的Delegate private delegate void CreateLiveContainerDelegate(); //從xml 中取得時際實際有多少個年份資料 private List xmlDataList = new List(); //透過取得的年份將MainEvent建立出來後放到該Buffer中 private List LiveContainerList = new List(); //Get Windows Resolution (根據 n * 1的螢幕取得windows的寬高) private static WindowsResolution CurrentMonitorCount = new WindowsResolution(); //public static ConfigSettingClass config = new ConfigSettingClass(GlobalFunction.ConfigSettingFilePath, CurrentMonitorCount); //當前載入的起始位置 0 : 代表當前第一個年份是xml資料的首年 private int currentLoadIndex = 0; //是否需要"當前"年份顯示在正中間 private bool NeedToGetCenter = true; private int CenterIndexValue = 0; //是否要有首頁動畫 private bool RunHomePageAnimation = true; //TouchDown 事件是否有發生 ? private bool isTouchDown = false; private bool isManipulatonEvent = false; private bool isAutoRun = false; //移動前 Horizontal.X的值 double MoveStartHorizontalX = 0.0; //移動後 Horizontal.X的值 double MoveEndHorizontalX = 0.0; //從開始到結束全部的移動距離 double MoveTotalDistance = 0.0; //容許開始到結束的全部移動量小於該值則為點擊事件 double AllowMaxDistance = 8000; //重新定位的Storyboard private Storyboard storyboardForLocate = new Storyboard(); private StoryBoardStatus storyboardStatus = StoryBoardStatus.StoryBoardIsStop; //重新定位的 Storyboard 速度調整係數 private int StorySmoothValue = 300; //輪播的Storyboard private Storyboard autoRunStoryboard = new Storyboard(); //當前歷史牆載入完成 private bool isHistoryWallLoadComplete = false; //狀態為手動或者輪播模式 public HistoryControlMode ControlMode = HistoryControlMode.Boot; //Loading~ HomePage hp; public CyclicScroller(int languageIndex) { InitializeComponent(); if (ConfigSettingClass.MainBackCollect == null) { MessageBox.Show("設定錯誤,請透過後台更新設定!!"); Application.Current.Shutdown(); return; } //初始化除了Spec外的基本設定 //refresh setting new ConfigSettingClass(GlobalFunction.ConfigSettingFilePath, CurrentMonitorCount); InitialWholeSetting(); if (GlobalFunction.isSolutionUsing4K) { MainEventWidth *= 2; MainEventHeight *= 2; YearEventHeight *= 2; this.uxMyScroll.Margin = new Thickness(this.uxMyScroll.Margin.Left, this.uxMyScroll.Margin.Top, this.uxMyScroll.Margin.Right, this.uxMyScroll.Margin.Bottom * 2); } if (CurrentMonitorCount.ncm == 0) { MessageBox.Show("螢幕解析度取得失敗, 可能會造成載入異常!!"); Application.Current.Shutdown(); return; } this.Loaded += new RoutedEventHandler(CyclicScroller_Loaded); this.KeyDown += new KeyEventHandler(CyclicScroller_KeyDown); } private void CyclicScroller_KeyDown(object sender, KeyEventArgs e) { //取得Ctrl + s進入後台設定 if (e.Key == Key.S && Keyboard.Modifiers == ModifierKeys.Shift) { Exception closeEx = CloseProcess("nLightenHistoryWallEdit"); if (closeEx != null) { Debug.WriteLine(closeEx.Message); } Thread.Sleep(100); Exception ex = OpenProcess(AppDomain.CurrentDomain.BaseDirectory + "nLightenHistoryWallEdit.exe"); if (ex != null) { MessageBox.Show(ex.Message); } } } void CyclicScroller_Loaded(object sender, RoutedEventArgs e) { //取得資料 if (!GetHistoryData()) { MessageBox.Show("資料準備中,敬請期待!"); Application.Current.Shutdown(); return; } //*設定規範值請參閱 SpecificationValue.cs file. SetSpecValue(); //設定當前語系 SetLanguage(); //設定回正被中斷時~應該回到的顯示位置 SetReturnPos(); //根據螢幕數量~顯示螢幕中會有幾個內容(children) ChildrenCount = GetChildrenCount(); //根據可以顯示的 Children 數量~新建出 Grid For 裝載DetailViewer CreateExtraUnitGrid(); //初始化該 ExtraUnitGrid ~包括 狀態 位置 InitializeExtraUnitGrid(); //拖動隱藏區塊顯示設定 SetDisplayPart(); //將首頁輪播 LoadBar 加到畫面中 AddHomePageAnimation(); //計算總事件~並將該直傳到Homepage中 CalcCountToHomePage(); //延遲載入~避免程式咬死 WpfDelayDoWork.DoBackgroundWork(CreateLiveConainer, 1000); } private void CreateLiveConainer() { if (xmlDataList.Count <= 0) { return; } //Loading Start LoadingStart(); //總共會有多少筆 MainEvent ? 透過 YearList 中的個數將 MainEvent 預先建立起來 CreatMainEvent(); //是否需要將首年顯示在中間 if (NeedToGetCenter) { CenterIndexValue = GetCenterIndexValue(); } //之後代表會有 ChildrenCount 個數量會在 Scrollviewer 當中 currentLoadIndex = GetIndexFromLeftSide(); currentLoadIndex -= CenterIndexValue; AddEventBlock(currentLoadIndex, false); //回正Storyboard BackToPosFromCurrentLoadIndex(currentLoadIndex); //自動輪播 GlobalFunction.CheckAutoRunTimer.Start(); isHistoryWallLoadComplete = true; } //回正 private void BackToPosFromCurrentLoadIndex(int currentLoadIndex) { isTouchDown = false; double dd = Math.Abs(MainEventWidth + NoneUseRange - uxMyScroll.HorizontalOffset) / StorySmoothValue; if (dd <= 0.3) { dd = 0.3; } else if (dd >= 0.5) { dd = 0.5; } //完成後由 storyboard 回到中間位置 DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromSeconds(dd), EasingFunction = new PowerEase() { EasingMode = EasingMode.EaseOut, Power = 2 }, }; ScrollViewerUtilities.UseMotionStop = false; Storyboard.SetTarget(dbOffset, (DependencyObject)this.FindName("uxMyScroll")); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(ScrollViewerUtilities.HorizontalOffsetProperty)); storyboardForLocate.Children.Add(dbOffset); storyboardForLocate.FillBehavior = FillBehavior.HoldEnd; dbOffset.From = uxMyScroll.HorizontalOffset; dbOffset.To = MainEventWidth + NoneUseRange; SetStoryBoardStatus(StoryBoardStatus.StoryBoardIsRun); } void storyboardForLocate_Completed(object sender, EventArgs e) { SetStoryBoardStatus(StoryBoardStatus.StoryBoardIsStop); if (ControlMode == HistoryControlMode.Boot) { ControlMode = HistoryControlMode.Manual; } //確實停止後才開始判斷是否為點擊sdlu if (storyboardStatus == StoryBoardStatus.StoryBoardIsStop) { if (MoveTotalDistance <= AllowMaxDistance) { //通知 判斷為點擊 SendInfoToLiveContainer(TouchorManipulation.TouchEvent); } else { //通知 判斷為Manipulation SendInfoToLiveContainer(TouchorManipulation.ManipulationEvent); } MoveTotalDistance = 0.0; //改變被點擊開的兩旁資訊 ChangeDetailSide(); } } //啟動或停止回正的storyboard private void SetStoryBoardStatus(StoryBoardStatus sbs) { if (sbs == StoryBoardStatus.StoryBoardIsRun) { storyboardForLocate.Begin(); storyboardStatus = sbs; } else if (sbs == StoryBoardStatus.StoryBoardIsStop) { storyboardForLocate.Stop(); storyboardStatus = sbs; } } #region 將每個年份事件區塊加到 Scrollviewer 中 /// /// 將要顯示的事件區塊加到 StackPanel 中 /// /// 從事件包(LiveContainerList)中取出事件的起始索引位置 /// 往左邊改變或者往右邊改變 private void AddEventBlock(int startIndex, bool IsRightSide) { if (ClearScrollChildren(IsRightSide)) { for (int index = 0; index < ChildrenCount + 2; index++) { int addcount = (startIndex + index) % LiveContainerList.Count; AddGridIntoScroll(addcount, index, true); } } else //如果不是第一次載入~代表該狀況為移動畫面造成改變~所以依照移動的方向做區塊的改變 { int index = 0; //由右到左 if (IsRightSide) { index = ChildrenCount + 1; } else //由左到右 { index = 0; } int addcount = (startIndex + index) % LiveContainerList.Count; AddGridIntoScroll(addcount, index, IsRightSide); } //改變年份區塊的索引值與顏色 ChangeBlockColor(); //**改變視角位置 (移動到中間的區塊)** if (IsRightSide) { uxMyScroll.ScrollToHorizontalOffset(uxMyScroll.HorizontalOffset - MainEventWidth); } else { uxMyScroll.ScrollToHorizontalOffset(uxMyScroll.HorizontalOffset + MainEventWidth); } } private void ChangeBlockColor() { //更新物件在Scroller中的索引位置~並改變其顏色 for (int count = 0; count < uxMyStackPanel.Children.Count; count++) { ((LiveContainer)uxMyStackPanel.Children[count]).Set_Get_ContainerIndex = count; if (count <= 1 || count >= ChildrenCount) { ((LiveContainer)uxMyStackPanel.Children[count]).ChangeControlColor(false); } else ((LiveContainer)uxMyStackPanel.Children[count]).ChangeControlColor(true); } } private bool ClearScrollChildren(bool IsRightSide) { //如果整個Panel都沒有物件的話代表這是第一次載入物件~所以不須執行任何移除物件的動作 if (uxMyStackPanel.Children.Count > 0) { if (IsRightSide) { //移除第一個 ((LiveContainer)uxMyStackPanel.Children[0]).Set_Get_ContainerIndex = -1; uxMyStackPanel.Children.RemoveAt(0); } else { //移除最後一個 ((LiveContainer)uxMyStackPanel.Children[uxMyStackPanel.Children.Count - 1]).Set_Get_ContainerIndex = -1; uxMyStackPanel.Children.RemoveAt(uxMyStackPanel.Children.Count - 1); } return false; } return true; } /// /// 新增一個區塊到 Stackpanel 中 /// /// 要新增的區塊是事件包 (LiveContainerList)中的哪一個 /// 主要是回報給Homepage, 是哪幾個年份區塊在stackpanel 中 /// 新增的方式是 Add or Insert private void AddGridIntoScroll(int addcount, int index, bool IsAddBlock) { if (IsAddBlock) { uxMyStackPanel.Children.Add(LiveContainerList[addcount]); } else { uxMyStackPanel.Children.Insert(0, LiveContainerList[addcount]); } //將初始完成後~顯示在畫面中的年份資料傳給Homepage if (RunHomePageAnimation) { if (index >= 1 && index <= ChildrenCount) { hp.xmlDataList.Add(LiveContainerList[addcount].xmlData); } } } #endregion /// /// 透過 YearList 中的個數將 MainEvent 預先建立起來"如不足則循環" /// private void CreatMainEvent() { //"如不足則循環"方式為~依照各螢幕數量不同給予不同的常數值 int staticvalue = GetCycleCount(); for (int index = 0; index < staticvalue; index++) { for (int count = 0; count < xmlDataList.Count; count++) { LiveContainer liveContainer = new LiveContainer(xmlDataList[count], MainEventWidth, MainEventHeight); //通知 LiveContainer 通道 liveContainer.ListenFromCyclicTouchStatus(this); //接收來自 LiveContainer 通道 liveContainer.LiveContainerBubbleToCyclicScrollerEvent += new LiveContainer.LiveContainerBubbleToCyclicScroller(ReceiveFromLiveContainerInfo); liveContainer.CreateLiveContainer(); LiveContainerList.Add(liveContainer); } } } /// /// 這邊的計算方式為~ /// 如果是單螢幕則全部需要ChildrenCount個加四個備份所以是ChildrenCount + 4個, /// 雙螢幕需要ChildrenCount個加四個備份所以是ChildrenCount + 4個, /// 三螢幕需要ChildrenCount個加四個備份所以是ChildrenCount + 4個 /// 如果xml中的年份不足, 則必須進行循環. 此result則為循環次數 /// /// private int GetCycleCount() { int result = 0; //如果設定的年份少於全部需要的則必須 switch (CurrentMonitorCount.ncm) { case MonitorFlag.Monitor1_1: case MonitorFlag.Monitor2_1: case MonitorFlag.Monitor3_1: case MonitorFlag.Monitor4_1: case MonitorFlag.Monitor5_1: case MonitorFlag.Monitor6_1: { result = (TotalShowChildren / xmlDataList.Count) + 1; break; } } return result; } public static T DeserializeFromJson(string json) { T deserializedProduct = JsonConvert.DeserializeObject(json); return deserializedProduct; } /// /// //取得 ini 中的資料 /// /// private bool GetHistoryData() { List eventgroups = new List(); HistoryWallEventJson hweventJson = new HistoryWallEventJson(); if (File.Exists(GlobalFunction.JsonFilePath)) { string jsonResult; xmlDataList.Clear(); using (StreamReader sr = new StreamReader(GlobalFunction.JsonFilePath)) { jsonResult = sr.ReadToEnd(); } hweventJson = DeserializeFromJson(jsonResult); eventgroups = hweventJson.EventGroups; if (hweventJson.EventGroups.Count <= 0) { return false; } for (int index = 0; index < hweventJson.EventGroups.Count; index++) { if (hweventJson.EventGroups[index].ListDates.Count > 0) { XmlData xmldata = new XmlData(hweventJson.EventGroups[index]); xmlDataList.Add(xmldata); } } } else { return false; } return true; } /// /// 自動移動 /// /// /// void AutoRunTimer_Tick(object sender, EventArgs e) { uxMyScroll.ScrollToHorizontalOffset(uxMyScroll.HorizontalOffset + 1); } private void uxMyScroll_ManipulationStarted(object sender, ManipulationStartedEventArgs e) { if (isHistoryWallLoadComplete) { SetStoryBoardStatus(StoryBoardStatus.StoryBoardIsStop); isTouchDown = true; isManipulatonEvent = false; MoveStartHorizontalX = uxMyScroll.HorizontalOffset; } e.Handled = true; } private void uxMyScroll_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { if (isTouchDown) { uxMyScroll.ScrollToHorizontalOffset(uxMyScroll.HorizontalOffset - e.DeltaManipulation.Translation.X); MoveTotalDistance += Math.Abs(uxMyScroll.HorizontalOffset - e.DeltaManipulation.Translation.X); } e.Handled = true; } private void uxMyScroll_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { if (isTouchDown) { isTouchDown = false; BackToPosFromCurrentLoadIndex(currentLoadIndex); } isManipulatonEvent = false; e.Handled = true; } private void uxMyScroll_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) { e.TranslationBehavior = new InertiaTranslationBehavior() { InitialVelocity = e.InitialVelocities.LinearVelocity, DesiredDeceleration = 20.0 * 96.0 / (1000.0 * 1000.0) }; e.Handled = true; } /// /// 改變被點擊開的兩旁資訊 /// private void ChangeDetailSide() { int count = ExtraUnitGridList.Count; for (int index = 0; index < count; index++) { if (ExtraUnitGridList[index].IsUsing != 0 && ExtraUnitGridList[index].Get_Set_BlockControlMode != ExtraUnitGrid.ControlMode.Extend) { int mappingStackpanel = index + 1; if (((LiveContainer)uxMyStackPanel.Children[mappingStackpanel]).uxYearStr.Text != ExtraUnitGridList[index].textblock.Text) { if (ExtraUnitGridList[index].Get_Set_BlockControlMode != ExtraUnitGrid.ControlMode.MinStatus) { ExtraUnitGridList[index].textblock.Text = ((LiveContainer)uxMyStackPanel.Children[mappingStackpanel]).uxYearStr.Text; } ThumbnailContainer thumbnailControl = new ThumbnailContainer(); List folderPaths = new List(); ExtraUnitGridList[index].DetailViewerControlHide(); folderPaths = GetThumbnailControl(mappingStackpanel); thumbnailControl.ImgPath = MediaUtilties.GetImageFromFolders(folderPaths.ToArray()); ExtraUnitGridList[index].BorderUp.VerticalAlignment = System.Windows.VerticalAlignment.Bottom; ExtraUnitGridList[index].BorderUp.Child = thumbnailControl; ExtraUnitGridList[index].DetailViewerControlShow(null, null); } } } } private Exception OpenProcess(string exePath) { if (File.Exists(exePath)) { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = exePath; try { Process startProcess = Process.Start(startInfo); return null; } catch (Exception ex) { return ex; } } else { return new Exception(exePath + "檔案不存在!"); } } private Exception CloseProcess(string processName) { try { bool isKill = false; System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses(); foreach (System.Diagnostics.Process myProcess in myProcesses) { if (myProcess.ProcessName == processName) { Debug.WriteLine(myProcess.ProcessName + " " + myProcess.MainWindowHandle.ToString()); myProcess.Kill(); isKill = true; } } if (isKill) { return null; } else { return new Exception("Cannot find " + processName); } } catch (Exception ex) { return ex; } } private void Window_PreviewTouchDown(object sender, TouchEventArgs e) { //停止輪播 StopAutoRunTheWall(); GlobalFunction.CheckAutoRunTimer.Stop(); } //避免點擊在非歷史軸的時, 歷史軸會因為輪播停止而卡住的狀況 private void Window_PreviewTouchUp(object sender, TouchEventArgs e) { if (!isManipulatonEvent && isHistoryWallLoadComplete && isAutoRun) { BackToPosFromCurrentLoadIndex(currentLoadIndex); } isAutoRun = false; if (!GlobalFunction.isVideoPlay) GlobalFunction.CheckAutoRunTimer.Start(); } private void uxMyScroll_ScrollChanged(object sender, System.Windows.Controls.ScrollChangedEventArgs e) { if (ControlMode == HistoryControlMode.Boot) { return; } MoveEndHorizontalX = uxMyScroll.HorizontalOffset; //手指頭往左邊的移動 if (MoveEndHorizontalX > MainEventWidth * 2 + NoneUseRange - (MainEventWidth / 2)) { autoRunStoryboard.Stop(); //判斷當前的Index是否超出"最大"容許範圍~進行調整 currentLoadIndex = GetIndexFromRightSide(); //重新加入EventBlock AddEventBlock(currentLoadIndex, true); if (ControlMode == HistoryControlMode.AutoRun) { SetAutoRunStoryBoard(MoveEndHorizontalX - MainEventWidth, MoveEndHorizontalX - MainEventWidth + MainEventWidth); autoRunStoryboard.Begin(); } } //手指頭往右邊的移動 else if (MoveEndHorizontalX < MainEventWidth + NoneUseRange - (MainEventWidth / 2)) { //判斷當前的Index是否低於"最小"容許範圍~進行調整 currentLoadIndex = GetIndexFromLeftSide(); //重新加入EventBlock AddEventBlock(currentLoadIndex, false); } } #region 切換語系與回首頁按鈕 private void ChangeLangBtn_Click(object sender, RoutedEventArgs e) { int changeLanIndex = 0; if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 0) { if (canUsingLangList[1]) { changeLanIndex = 1; } else if (canUsingLangList[2]) { changeLanIndex = 2; } else if (canUsingLangList[3]) { changeLanIndex = 3; } } else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 1) { if (canUsingLangList[2]) { changeLanIndex = 2; } else if (canUsingLangList[3]) { changeLanIndex = 3; } else if (canUsingLangList[0]) { changeLanIndex = 0; } } else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 2) { if (canUsingLangList[3]) { changeLanIndex = 3; } else if (canUsingLangList[0]) { changeLanIndex = 0; } else if (canUsingLangList[1]) { changeLanIndex = 1; } } else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 3) { if (canUsingLangList[0]) { changeLanIndex = 0; } else if (canUsingLangList[1]) { changeLanIndex = 1; } else if (canUsingLangList[2]) { changeLanIndex = 2; } } if (changeLanIndex == 0) { ConfigSettingClass.MainBackCollect.DefaultLangIndex = changeLanIndex; System.Windows.Application.Current.Properties["Language"] = "Language1"; } else if (changeLanIndex == 1) { ConfigSettingClass.MainBackCollect.DefaultLangIndex = changeLanIndex; System.Windows.Application.Current.Properties["Language"] = "Language2"; } else if (changeLanIndex == 2) { ConfigSettingClass.MainBackCollect.DefaultLangIndex = changeLanIndex; System.Windows.Application.Current.Properties["Language"] = "Language3"; } else if (changeLanIndex == 3) { ConfigSettingClass.MainBackCollect.DefaultLangIndex = changeLanIndex; System.Windows.Application.Current.Properties["Language"] = "Language0"; } uxMainLangBtnL.Content = ConfigSettingClass.MainBackCollect.LangText[ConfigSettingClass.MainBackCollect.DefaultLangIndex]; uxMainLangBtnR.Content = ConfigSettingClass.MainBackCollect.LangText[ConfigSettingClass.MainBackCollect.DefaultLangIndex]; for (int i = 0; i < LiveContainerList.Count; i++) { LiveContainerList[i].WriteYearBarStr(); //改變事件區塊中顯示文字分兩部分 //1. 已經在事件區塊中顯示的 Planerotate LiveContainerList[i].ChangeCurPlaneRotateLan(); //2. 在緩衝區中待顯示的 Planerotate //LiveContainerList[i].ChangePlaneRotateLan(); } for (int j = 0; j < ExtraUnitGridList.Count; j++) { if (ExtraUnitGridList[j].curDataIndex != -1) { ExtraUnitGridList[j].textblock.Text = ((LiveContainer)uxMyStackPanel.Children[j + 1]).uxYearStr.Text; } } } private void HomeBtn_Click(object sender, RoutedEventArgs e) { if (HomeBackInforEvent != null) this.Dispatcher.BeginInvoke(HomeBackInforEvent, DispatcherPriority.Background); } #endregion } public class WpfDelayDoWork { public static void DoWork(Action action, int millisecond = 300) { new Action(DoWorkAsync).BeginInvoke(Dispatcher.CurrentDispatcher, action, millisecond, null, null); } public static void DoBackgroundWork(Action action, int millisecond = 300) { new Action(DoBackgroundWorkAsync).BeginInvoke(Dispatcher.CurrentDispatcher, action, millisecond, null, null); } static void DoWorkAsync(Dispatcher dispatcher, Action action, int millisecond) { System.Threading.Thread.Sleep(millisecond); dispatcher.BeginInvoke(action); } static void DoBackgroundWorkAsync(Dispatcher dispatcher, Action action, int millisecond) { System.Threading.Thread.Sleep(millisecond); dispatcher.Invoke(action, DispatcherPriority.Background); } } }