如何从另一个类调用ICommand属性

时间:2019-09-14 18:44:58

标签: c# wpf mvvm

我已经用ContextMenus实现了一个弹出激活,当用户右键单击taskbarIcon时,其中有ShowWindowCommand个MenuItem。当用户单击该窗口时,它将最大化窗口。以下是ContextMenus的代码:

NotifyIcon.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:tb="http://www.hardcodet.net/taskbar"
                    xmlns:local="clr-namespace:MyProject.ViewModels">

    <ContextMenu x:Shared="false" x:Key="SysTrayMenu">
        <MenuItem Header="Show Window" Command="{Binding ShowWindowCommand}" />
        <MenuItem Header="Hide Window" Command="{Binding HideWindowCommand}" />
        <Separator />
        <MenuItem Header="Exit" Command="{Binding ExitApplicationCommand}" />
    </ContextMenu>

    <tb:TaskbarIcon x:Key="NotifyIcon"
                    IconSource="/tg_shield_copy.ico"
                    ToolTipText="MyProject"
                    DoubleClickCommand="{Binding ShowWindowCommand}"
                    ContextMenu="{StaticResource SysTrayMenu}">

        <tb:TaskbarIcon.DataContext>
            <local:NotifyIconViewModel/>
        </tb:TaskbarIcon.DataContext>
    </tb:TaskbarIcon>

</ResourceDictionary>

点击ShowWindowCommand后,它将调用NotifyIconViewModel类中的ICommand属性

NotifyIconViewModel.cs

 public class NotifyIconViewModel : BootstrapperBase
    {
        /// <summary>
        /// Shows a window, if none is already open.
        /// </summary>
        public ICommand ShowWindowCommand
        {
            get
            {
                return new DelegateCommand
                {
                    CanExecuteFunc = () => Application.Current.MainWindow == null,
                    CommandAction = () =>
                    {
                        DisplayRootViewFor<ShellViewModel>();
                    }
                };
            }
        }

        /// <summary>
        /// Hides the main window. This command is only enabled if a window is open.
        /// </summary>
        public ICommand HideWindowCommand
        {
            get
            {
                return new DelegateCommand
                {
                    CommandAction = () => Application.Current.MainWindow.Close(),
                    CanExecuteFunc = () => Application.Current.MainWindow != null
                };
            }
        }


        /// <summary>
        /// Shuts down the application.
        /// </summary>
        public ICommand ExitApplicationCommand
        {
            get
            {
                return new DelegateCommand { CommandAction = () => Application.Current.Shutdown() };
            }
        }
    }

    /// <summary>
    /// Simplistic delegate command for the demo.
    /// </summary>
    public class DelegateCommand : ICommand
    {
        public System.Action CommandAction { get; set; }
        public Func<bool> CanExecuteFunc { get; set; }

        public void Execute(object parameter)
        {
            CommandAction();
        }

        public bool CanExecute(object parameter)
        {
            return CanExecuteFunc == null || CanExecuteFunc();
        }

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

    }

现在我想从另一个类中调用ICommand属性,例如:

ServerModule.cs

 public class ServerModule : NancyModule
{
   public ServerModule()
   {
      Post ("/Message", (args) =>
      {
        // Call ShowWindowCommand from here
      }
   }
}

我的问题是,如何从ServerModule.cs类调用ICommand属性,这与我在NotifyIcon.xaml中使用绑定命令调用的属性相同

更新

已经在使用代码建议,但是会出现异常

  

'MyProject.exe'(CLR v4.0.30319:MyProject.exe):已加载'C:\ WINDOWS \ Microsoft.Net \ assembly \ GAC_MSIL \ System.Dynamic \ v4.0_4.0.0.0__b03f5f7f11d50a3a \ System.Dynamic。 dll”。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。

     

线程0x550c已退出,代码为0(0x0)。

     

线程0x52e4已退出,代码为0(0x0)。

     

抛出异常:WindowsBase.dll中的'System.InvalidOperationException'

     

抛出异常:WindowsBase.dll中的'System.InvalidOperationException'

     

线程0x43d8已退出,代码为0(0x0)。

     

抛出异常:WindowsBase.dll中的'System.InvalidOperationException'

     

线程0x52b8已退出,代码为0(0x0)。

     

线程0x333c已退出,代码为0(0x0)。

2 个答案:

答案 0 :(得分:0)

ServerModule需要对公开所需命令的对象实例的引用:

public class ServerModule : NancyModule
{
   private NotifyIconViewModel CommandViewModel { get; }

   public ServerModule(NotifyIconViewModel commandViewModel)
   {
      this.CommandViewModel = commandViewModel;
      Post ("/Message", (args) =>
      {
        this.CommandViewModel.ShowWindowCommand.Execute();
      }
   }
}

如果您使用的是MVVM,请确保ServerModule是视图或视图模型组件的类。否则,您将违反设计模式(因为您的模型将调用它们中的任何一个)。如果ServerModule是模型的一部分,则必须重新设计应用程序。

答案 1 :(得分:0)

BionicCode 中的解决方案对我有帮助,非常感谢。我只是添加了一个应用程序调度程序,以避免像下面的代码那样cross-thread exception

public class ServerModule : NancyModule
{
   private NotifyIconViewModel CommandViewModel { get; }

   public ServerModule(NotifyIconViewModel commandViewModel)
   {
     this.CommandViewModel = commandViewModel;

     Post ("/Message", (args) =>
     {
       Application.Current.Dispatcher.Invoke(delegate
       {
          CommandViewModel.ShowWindowCommand.Execute (null);
       });
     }
   }
}