C# 使用 MVVM 在 WPF 中绑定命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16314828/
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-08-10 00:43:37  来源:igfitidea点击:

Bind command in WPF using MVVM

c#.netwpfmvvm

提问by Narendra

I am learning MVVMand WPF. I have a xamlfile in my project and which has a simple click event handler in the code behind.

我正在学习MVVMWPFxaml我的项目中有一个文件,后面的代码中有一个简单的单击事件处理程序。

Now I want to do the same in MVVM. I read a lot of articles and also read many answers in sof. But still unable to do this.

现在我想在MVVM 中做同样的事情。看了很多文章,也在sof上看了很多答案。但仍然无法做到这一点。

Can anyone please give a simple example in which a button clickevent is done in MVVM.

任何人都可以举一个简单的例子,其中在MVVM 中完成按钮单击事件。

Edit

编辑

<Window x:Class="WhiteBalance.BaseCalWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:uc="clr-namespace:NumberUpDownControl;assembly=NumberUpDownControl"
        xmlns:viewn="clr-namespace:WhiteBalance.ViewModels"
        Title="RefImgSettingWindow"  Height="900" Width="1000" ResizeMode="NoResize" 
        BorderThickness="4">
    <Window.Resources>
        <viewn:DashBoardViewModel x:Key="demokey"></viewn:DashBoardViewModel>
    </Window.Resources>
    <Grid x:Name="gdParent" DataContext="{StaticResource demokey}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="490" />
            <ColumnDefinition Width="488*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="300" />
            <RowDefinition Height="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">
            <Label Content="{Binding Path=NAME,Mode=TwoWay}" Height="28" Name="lblTest" />
            <Button Content="Capture" Height="23" Name="btnCapture" Width="75" Command="{Binding Path=SaveCommand}"
                             Canvas.Left="94" Canvas.Top="254" />

        </StackPanel>
    </Grid>
</Window>

namespace WhiteBalance.ViewModels
{
    public class DashBoardViewModel: ObservableObject
    {
        private string _name = "dsqdasd";

        public string NAME
        {
            get { return _name; }
            set { _name = value; }
        }

        public ICommand SaveCommand
        {
            get;
            set;
        }

        private bool CanExecuteSaveCommand()
        {
            return true;    // !string.IsNullOrEmpty(LastName);
        }

        private void CreateSaveCommand()
        {
            SaveCommand = new RelayCommand(SaveExecute, CanExecuteSaveCommand);
        }

        public void SaveExecute()
        {
            //Person.Save(_newPerson);
            NAME = "Changed Name";
        }

        public DashBoardViewModel()
        {
            //objModel.TestText = "This will change";
            NAME = "TestName";
        }
    }
}

Thanks in advance.

提前致谢。

采纳答案by slugster

You can bind the Commandproperty of the button to any property that returns ICommand. Prismimplements a nice convenient command called DelegateCommandthat is very easy to use (here is a knock-offof it):

您可以将按钮的Command属性绑定到任何返回ICommand 的属性。Prism实现了一个非常方便的命令,称为DelegateCommand,它非常易于使用(这里是它的一个仿制品):

public ICommand MyButtonClickCommand 
{
    get { return new DelegateCommand<object>(FuncToCall, FuncToEvaluate); }
}

private void FuncToCall(object context)
{
    //this is called when the button is clicked
}

private bool FuncToEvaluate(object context)
{
    //this is called to evaluate whether FuncToCall can be called
    //for example you can return true or false based on some validation logic
    return true;
}



<Button x:Name="myButton" Command="{Binding MyButtonClickCommand}" />

The CodeProject example How to use Commands in WPFhas a very similar example with code that you can easily work through. The previous Stack Overflow question has an example using RoutedCommands that are statically bound to: How to bind Close command to a button, and How to bind WPF button to a command in ViewModelBase?has a slightly more advanced example.

CodeProject 示例How to use Commands in WPF有一个非常相似的示例,其中包含您可以轻松完成的代码。之前的 Stack Overflow 问题有一个使用静态绑定到的 RoutedCommands 的示例:如何将关闭命令绑定到按钮,以及如何将 WPF 按钮绑定到 ViewModelBase 中的命令?有一个稍微高级一点的例子。

回答by CookiePolicy

Seeing a lot of answers implementing this ICommand interface, I suggest a simpler option, which is to use the built in System.Windows.Input

看到很多实现这个 ICommand 接口的答案,我建议一个更简单的选择,那就是使用内置的 System.Windows.Input

Here's an example:

下面是一个例子:

Xaml View:

Xaml 视图:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="SomeDialog"
    SizeToContent="WidthAndHeight"
    WindowStartupLocation="CenterOwner" 
    ResizeMode="CanResizeWithGrip">

    <StackPanel>
        <Button Width="Auto" Command="{Binding ClearCommand}" Content="Clear"/>
    </StackPanel>

</Window>

View Code behind:

查看后面的代码:

using System.Windows;

public partial class SomeDialog : Window
{
    public SomeDialog()
    {
        var vm = new ViewModel();
        DataContext = vm;
        CommandBindings.AddRange(vm.Commands);
        InitializeComponent();
    }
 }

View model:

查看型号:

using System.Windows.Input;

public class ViewModel : ViewModelBase
{
    readonly CommandBindingCollection commands = new CommandBindingCollection();

    public static RoutedUICommand ClearCommand { get; set; } = new RoutedUICommand("Clear", "ClearCommand", typeof(ErrorDialog));

    public CommandBindingCollection Commands
    {
        get
        {
            commands.Add(new CommandBinding(ClearCommand, OnClearExecuted);
            return commands;
        }
    }

    void OnClearExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        view.DialogResult = true; //Indicate things
        view.Close(); //Close the window
    }
}

Call like this:

像这样调用:

public void OpenSomeDialog()
{
    var dialog = new SomeDialog() {Owner = Application.Current.MainWindow};
    bool? b = dialog.ShowDialog();
    if (b != null && (bool) b)
        //Do things
}

Now go dialog things.

现在去对话的东西。