2016-12-02 111 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为他的帮助做出了贡献!