2016-12-02 123 views
1

當我使用NotifyIcon時,似乎無法在我的ViewModel中使用我的XAML代碼成功運行方法。該方法正確執行,如使用斷點的調試模式進行測試,但View中沒有任何反應。C#MVVM使用NotifyIcon從代碼隱藏中調用ViewModel方法

有問題的方法是RefreshData,它可以從視圖中的按鈕(按預期工作)或右鍵單擊NotifyIcon並選擇刷新數據(不執行任何操作)來調用。我將在下面發佈相關代碼。任何幫助,將不勝感激!在代碼隱藏

主窗口構造

public MainWindow() 
    { 
     try 
     { 
      MM = new MMViewModel(); 
      InitializeComponent();     
      DataContext = MM; 

      _notifyIcon = new NotifyIcon(); 
      _notifyIcon.DoubleClick += (s, args) => ShowMainWindow(this); 
      _notifyIcon.Icon = Migration_Monitor_v2.Properties.Resources.mmc; 
      _notifyIcon.Visible = true; 

      Closing += MainWindow_Closing; 

      CreateContextMenu(); 
     } 
     catch (Exception e) 
     { 
      logger.Error("App failed with exception: ", e); 
     } 
    } 

    private void CreateContextMenu() 
    { 
     _notifyIcon.ContextMenuStrip = new ContextMenuStrip(); 
     _notifyIcon.ContextMenuStrip.Items.Add("Refresh Data").Click += (s,e) => MM.RefreshData(); 
     _notifyIcon.ContextMenuStrip.Items.Add("Exit").Click += (s, e) => ExitApplication(this); 
    } 

RefreshData方法在視圖模型

public void RefreshData() 
    { 
     InfoPanelVisible = Visibility.Hidden; 
     InfoSummaryVisible = Visibility.Visible; 
     Task.Run(() => LoadData()); 
     n = DateTime.Now; 
     ProgressBarText = "Click a project to show progress"; 
     ProgressBarValue = 0; 
     lastRefresh.Reset(); 
     lastRefresh.Start(); 
    } 

稱爲LoadData方法(和相關方法)從RefreshData

(來自刷新按鈕在View執行時作品)
public async void LoadData() 
    { 
     IsLoading = Visibility.Visible; 
     await GetWebApiInfo(); 
     MonitorData downloadInfo = main; 
     try { AssignDataToControls(downloadInfo); } 
     catch (Exception e) { Console.WriteLine("Error: " + e); } 
     finally { IsLoading = Visibility.Hidden; } 
    } 

    public void AssignDataToControls(MonitorData mon) 
    { 
     MainPanel.Clear(); 
     MonitorText.Clear(); 
     mon.MainPanel.ToList().ForEach(x => MainPanel.Add(x)); 
     mon.MonitorText.ToList().ForEach(x => MonitorText.Add(x)); 
     Information = mon.Information; 
     ProgressData = mon.progList; 
    } 

    public async Task GetWebApiInfo() 
    { 
     var url = "::::WEB API ADDRESS::::"; 
     string responseFromServer; 
     using (HttpClient _client = new HttpClient()) 
     using (var dataStream = await _client.GetStreamAsync(url)) 
     using (var reader = new StreamReader(dataStream, Encoding.Unicode)) 
      responseFromServer = await reader.ReadToEndAsync(); 
     var deserializer = new JavaScriptSerializer(); 
     main = deserializer.Deserialize<MonitorData>(responseFromServer); 
    } 

RefreshCommand from ViewModel Commands.cs fil e

internal class RefreshCommand : ICommand 
{ 
    public RefreshCommand(MMViewModel viewModel) 
    { 
     _viewModel = viewModel; 
    } 

    private MMViewModel _viewModel; 

    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _viewModel.CanRefresh; 
    } 

    public void Execute(object parameter) 
    { 
     _viewModel.RefreshData(); 
    } 
} 
+0

沒有東西在我身上彈出。你聲稱「該方法正確執行」,但不清楚你在說什麼方法。例如,如果你想在每個方法的開始處放置斷點,那麼點擊通知圖標,你實際設法走多遠的調用堆棧?您可以將一個Action添加到斷點,以便只打印剛剛在調試控制檯中執行的方法的名稱,這很方便。 – Will

+0

接下來,我會檢查視圖模型是您認爲它是什麼的假設。在LoadData方法中放置一個斷點。從任務欄觸發它,當它被命中時,將一個對象ID分配給'this'(如果你不知道對象ID如何工作,則搜索該術語)。接下來,從窗口中觸發它。當命中斷點時,檢查'this'來查看它是否有對象ID。如果沒有,你的數據上下文正在改變。 – Will

+0

對於CompositeCommand來說,這看起來像是一份工作。這是一個「shell」命令,允許各種虛擬機訂閱它以處理CanExecute/Execute。 – SledgeHammer

回答

0

解決了這個問題。問題是我的ViewModel被構建了三個不同的時間,所以不清楚該命令正在引用哪個實例。

爲了解決這個問題,我刪除了在我的XAML窗口定義空間中對ViewModel的引用。有2個引用我認爲我需要將ViewModel作爲本地命名空間(即x:local.VM =「MM.MyViewModel」)。刪除後,ViewModel只構造一次,所有代碼都按預期運行。感謝@Will爲他的幫助做出了貢獻!