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

C# 使用MVVM在WPF中绑定命令,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我正在学习MVVM和WPF。我的项目中有一个xaml文件,在代码背后有一个简单的click事件处理程序 现在我想在MVVM中做同样的事情。我读了很多文章,也读了很多关于软件的答案。但仍然无法做到这一点 任何人都可以给出一个简单的例子,其中按钮点击事件在MVVM中完成 编辑 <Window x:Class="WhiteBalance.BaseCalWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/prese

我正在学习MVVM和WPF。我的项目中有一个
xaml
文件,在代码背后有一个简单的click事件处理程序

现在我想在MVVM中做同样的事情。我读了很多文章,也读了很多关于软件的答案。但仍然无法做到这一点

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

编辑

<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";
        }
    }
}

命名空间WhiteBalance.ViewModels
{
公共类仪表板视图模型:ObserveObject
{
私有字符串_name=“dsqdasd”;
公共字符串名
{
获取{return\u name;}
设置{u name=value;}
}
公共ICommand SaveCommand
{
得到;
设置
}
私人布尔CanExecuteSaveCommand()
{
返回true;//!string.IsNullOrEmpty(LastName);
}
私有void CreateSaveCommand()
{
SaveCommand=新的RelayCommand(SaveExecute、CanExecuteSaveCommand);
}
公共void SaveExecute()
{
//Person.Save(_newPerson);
NAME=“更改名称”;
}
公共仪表板视图模型()
{
//objModel.TestText=“这将改变”;
NAME=“TestName”;
}
}
}
提前感谢。

您可以将按钮的属性绑定到返回的任何属性。实现了一个非常方便的命令,名为,非常易于使用:

公共ICommand MyButtonClickCommand
{
获取{返回新的DelegateCommand(FuncToCall,FuncToEvaluate);}
}
私有void FuncToCall(对象上下文)
{
//单击该按钮时,将调用此函数
}
私有布尔函数赋值(对象上下文)
{
//调用它是为了评估是否可以调用FuncToCall
//例如,您可以根据某些验证逻辑返回true或false
返回true;
}

CodeProject示例有一个非常类似的示例,其中包含您可以轻松使用的代码。上一个堆栈溢出问题有一个使用RoutedCommands(静态绑定到:)的示例,还有一个更高级的示例。

看到许多实现此ICommand接口的答案,我建议使用一个更简单的选项,即使用内置的
System.Windows.Input

下面是一个例子:

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>
视图模型:

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
    }
}
这样称呼:

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

现在开始对话。

您使用的是MVVM框架吗?您尝试过什么?是否强制使用MVVM框架?我不知道有什么框架。我唯一得到的是我需要使用ICommand,但我不知道如何使用它以及ViewModel中需要做哪些更改。不知道,但这很有帮助,我建议使用MVVM Light Thank@slugster。DelegateCommand是系统定义的类还是我需要创建它?我正在检查您提供的链接。@Narendra它是在Prism库中定义的,您只需要引用它们,或者查看到仿冒版本的链接。我已经添加了有问题的最近更改。你能告诉我为什么它没有调用所需的函数吗?@Narendra从我看到的情况来看,你从来没有调用过
CreateSaveCommand()
,所以
SaveCommand
的值将为空。这是一个很好的答案。我向上投票,并在我的解决方案中使用了一些改进,将按钮文本绑定到RouteDuicCommand.text属性:
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
    }
}
public void OpenSomeDialog()
{
    var dialog = new SomeDialog() {Owner = Application.Current.MainWindow};
    bool? b = dialog.ShowDialog();
    if (b != null && (bool) b)
        //Do things
}