【问题标题】:Bind command in WPF using MVVM使用 MVVM 在 WPF 中绑定命令
【发布时间】:2013-04-25 06:07:11
【问题描述】:

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

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

谁能举一个简单的例子,在 MVVM 中完成按钮 click 事件。

编辑

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

提前致谢。

【问题讨论】:

  • 你在使用任何 MVVM 框架吗?你试过什么?
  • 必须使用MVVM框架吗?我不知道任何框架。我唯一得到的是我需要使用 ICommand 但如何使用它以及 ViewModel 中需要进行哪些更改,我不知道。
  • 不,但它有很大帮助,我推荐 MVVM Light galasoft.ch/mvvm

标签: c# .net wpf mvvm


【解决方案1】:

您可以将按钮的Command 属性绑定到任何返回ICommand 的属性。 Prism 实现了一个非常方便的命令,称为 DelegateCommand,非常易于使用(其中的here is a knock-off):

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

CodeProject 示例How to use Commands in WPF 有一个非常相似的示例,其中包含您可以轻松完成的代码。上一个 Stack Overflow 问题有一个使用静态绑定到的 RoutedCommands 的示例:How to bind Close command to a buttonHow to bind WPF button to a command in ViewModelBase? 有一个稍微高级的示例。

【讨论】:

  • 谢谢@slugster。 DelegateCommand 是系统定义的类还是我需要创建它?我正在检查您提供的链接。
  • @Narendra 是在 Prism 库中定义的,你只需要引用它们,或者查看仿冒版本的链接。
  • 我已经添加了最近的更改。你能说出为什么它没有调用所需的函数吗?
  • @Narendra 据我所知,您从不调用CreateSaveCommand(),因此SaveCommand 的值将为空。
【解决方案2】:

看到很多实现这个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;

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

查看模型:

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
}

现在进行对话。

【讨论】:

  • 这么好的答案。我赞成并在我的解决方案中使用了将按钮文本绑定到 RoutedUICommand.Text 属性的一点改进:&lt;Button Command="{Binding ClearCommand}" Content="{Binding ClearCommand.Text}"/&gt;
  • 你的例子有问题。在ViewModel 类中,每次检索Commands 属性时,都会将ClearCommand 的新CommandBinding 添加到commands 集合中。代码应该只在实例化时将CommandBinding 添加到集合中。
猜你喜欢
  • 1970-01-01
  • 2015-06-07
  • 2010-11-06
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2014-11-06
相关资源
最近更新 更多