wpf 在视图模型中使用 ICommand 可以吗

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15370129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:02:45  来源:igfitidea点击:

Is it okay to use ICommand in view-model

c#wpfmvvm

提问by Chamika Sandamal

Most of the WPF mvvm applications, we are using ICommandin the view-model. But it is referring to System.Windows.Input. so the view-model is now tightly couple with System.Windows.Inputnamespace. according to my understanding view-model should be able to use in normal C# winform application or asp.net application.

我们ICommand在视图模型中使用的大多数 WPF mvvm 应用程序。但它指的是System.Windows.Input. 所以视图模型现在与System.Windows.Input命名空间紧密耦合。根据我的理解,view-model 应该可以在普通的 C# winform 应用程序或 asp.net 应用程序中使用。

Normally we are using following code lines to the command with RelayCommandimplementation.

通常我们使用以下代码行来执行命令RelayCommand

private RelayCommand testCommand;// or private ICommand testCommand;

public ICommand TestCommand
{
    get
    {
        return testCommand ?? 
            (testCommand = new RelayCommand(param => Test()));
    }
}

public void Test()
{

}

What i feel is we need to remove all the ICommandand use RelayCommandinstead. So we can eliminate the System.Windowsnamespace from the view-model. so final code will looks like this,

我觉得我们需要删除所有ICommand并使用它RelayCommand。所以我们可以System.Windows从视图模型中消除命名空间。所以最终的代码看起来像这样,

private RelayCommand testCommand;

public RelayCommand TestCommand
{
    get
    {
        return testCommand ?? 
            (testCommand = new RelayCommand(param => Test()));
    }
}

public void Test()
{

}

Any suggestions on this approach? or is there any way to eliminate the System.Windowsnamespace from the view-model?

关于这种方法的任何建议?或者有什么方法可以System.Windows从视图模型中消除命名空间?

回答by Reed Copsey

Any suggestions on this approach?

关于这种方法的任何建议?

This still doesn't decouple you from System.Windows.Inputas RelayCommandstill must implement ICommand, even if it's indirectly implementing it.

这仍然不会使您与System.Windows.Inputas RelayCommandstill must implement 分离ICommand,即使它是间接实现它。

Implementing ICommandwithin the ViewModel is one of those things that tends to be required in order to be pragmatic. Ideally, ICommand(or a similar interface) would have been implemented in a namespace that wasn't XAML specific. That being said, it is supported directly within the Portable Class Libraries, so it is not tied to a specificframework (WPF, Silverlight, Phone, etc) as much as XAML in general.

ICommand在 ViewModel 中实现是为了务实往往需要的事情之一。理想情况下,ICommand(或类似的接口)将在非 XAML 特定的命名空间中实现。也就是说,它在Portable Class Libraries 中得到了直接支持,因此它不像一般的 XAML那样依赖于特定的框架(WPF、Silverlight、Phone 等)。

回答by Meirion Hughes

Pretty simple to avoid coupling your ViewModel to ICommand, if you want to. Probably not a bad idea, WPF will probably go the way of MFC one day. Overkill? maybe, but here is ahow:

如果您愿意,可以很简单地避免将 ViewModel 与 ICommand 耦合。可能不是一个坏主意,WPF 可能有一天会走 MFC 的道路。矫枉过正?也许,但这是一个方法:

In your view:

在您看来:

<StackPanel>
    <Button Command="{Binding Path=MyCommand}"> Do it! Kill me Now!</Button>
    <TextBlock Text="{Binding Path=Message}"></TextBlock>
</StackPanel>

Inject your ViewModel into your DataContext, Take the responsibility for the native commands, out of your view model:

将您的 ViewModel 注入到您的 DataContext 中,从您的视图模型中承担本机命令的责任:

public class ViewModel : INotifyPropertyChanged
{
    public string Message { get; set; }
    public object MyCommand { get; set; }


    public void OnMyCommand(object parameter)
    {
        Message += "I Ran something" + Environment.NewLine;
    }

    public bool CanMyCommand(object parameter)
    {
        return true;
    }

    // Injected Native Command handler
    public ViewModel(ICommandFactory factory)
    {
        MyCommand = factory.CreateInstance(OnMyCommand, CanMyCommand);
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Note I'm using FODYto weave inthe property change handler. INotifyPropertyChanged is System.dll btw.

注意我使用FODY编织属性更改处理程序。INotifyPropertyChanged 是 System.dll 顺便说一句。

Now, Bind this contract:

现在,绑定这个合约:

public interface ICommandFactory
{
    object CreateInstance(Action<object> action, Func<object, bool> predicate);
}

... to something that will give you a native Command object;

... 给你一个本机 Command 对象的东西;

public class NativeCommand : ICommand
{
    private readonly Action<object> _action;
    private readonly Func<object, bool> _predicate;

    public NativeCommand(Action<object> action, Func<object, bool> predicate)
    {
        _action = action;
        _predicate = predicate;
    }

    public bool CanExecute(object parameter)
    {
        return _predicate(parameter);
    }

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

    public event EventHandler CanExecuteChanged;
}


public class NativeCommandFactory : ICommandFactory
{
    public object CreateInstance(Action<object> action, Func<object, bool> predicate)
    {
        return new NativeCommand(action, predicate);
    }
}

Bind<ICommandFactory>().To<NativeCommandFactory>();

Bind<ICommandFactory>().To<NativeCommandFactory>();

Voilà, decoupled commands.

瞧,解耦的命令。

running

跑步

Also note, your injection is done at initial application start. Your ViewModel is decoupled from whatever IoC container you choose.

另请注意,您的注入是在初始应用程序启动时完成的。您的 ViewModel 与您选择的任何 IoC 容器分离。

回答by Marty Dill

Well, in theory, you are pretty much right. It would if nice of ICommand was completely UI-platform-independent.

好吧,从理论上讲,您说得非常正确。如果 ICommand 的优点是完全独立于 UI 平台,那就太好了。

But from a practical standpoint, if you are using MVVM in a WPF app, there's a pretty good chance you are fairly dependent on WPF's databinding and datatemplating capabilities anyway. Trying to stick a WinForms UI on top of something like that would likely require a significant amount of extra effort.

但从实际的角度来看,如果您在 WPF 应用程序中使用 MVVM,那么无论如何您很可能相当依赖 WPF 的数据绑定和数据模板功能。试图将 WinForms UI 放在类似的东西之上可能需要大量的额外工作。

I've worked on some fairly large WPF/MVVM projects in the past. We considered MVVM to be a way of separating the specific details of the UI from the code - not so that we could switch to WinForms/ASP.NET/whatever, but so that we could change the look and feel of our UI (i.e. edit the XAML) without having to change the ViewModels. In this respect, MVVM worked perfectly.

我过去曾参与过一些相当大的 WPF/MVVM 项目。我们认为 MVVM 是将 UI 的特定细节与代码分离的一种方式——不是为了我们可以切换到 WinForms/ASP.NET/whatever,而是为了我们可以改变我们 UI 的外观(即编辑XAML),而无需更改 ViewModel。在这方面,MVVM 工作得很好。

If you are really concerned about sharing code across multiple types of projects, it might be better to try and put your common code in a typical 'Business Layer'-type class library, instead of in view model.

如果您真的很关心在多种类型的项目之间共享代码,最好尝试将您的公共代码放在典型的“业务层”类型的类库中,而不是放在视图模型中。