MVVM,数据绑定命令

时间:2011-03-19 11:13:30

标签: silverlight xaml data-binding mvvm

我已经开始在Silverlight中使用与MVVM模式的数据绑定。对我来说有一个问题。 我有一个列表框,当我选择一个项目时,View-Model中的一个属性必须改变它的值。我实现了DelegateCommand并制作了自定义CommandListBox类,如下所示

public class DelegateCommand<T> : ICommand
{
    private readonly Action<T> _execute;
    private readonly Predicate<T> _canExecute;

    public DelegateCommand(Action<T> execute)
        : this(execute, x => true)
    {
    }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute)
    {
        if (canExecute == null) throw new ArgumentNullException("canExecute");
        if (execute == null) throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute((T)parameter);
    }

    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged.DynamicInvoke(this);//.Raise(this);
    }
}

public class DelegateCommand : DelegateCommand<object>
{
    public DelegateCommand(Action execute)
        : base(execute != null ? x => execute() : (Action<object>)null)
    {
    }

    public DelegateCommand(Action execute, Func<bool> canExecute)
        : base(execute != null ? x => execute() : (Action<object>)null,
                canExecute != null ? x => canExecute() : (Predicate<object>)null)
    {
    }
}

public class CommandListBox : ListBox
{
    public CommandListBox()
    {
        SelectionChanged += (sender, e) =>
        {
            if (Command != null && Command.CanExecute(CommandParameter))
                Command.Execute(CommandParameter);
        };
    }

    public static DependencyProperty CommandProperty =
        DependencyProperty.Register("Command",
                                    typeof(ICommand), typeof(CommandListBox),
                                    new PropertyMetadata(null, CommandChanged));

    private static void CommandChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
        var treeList = source as CommandListBox;
        if (treeList == null) return;

        treeList.RegisterCommand(args.OldValue as ICommand, args.NewValue as ICommand);
    }

    private void RegisterCommand(ICommand oldCommand, ICommand newCommand)
    {
        if (oldCommand != null)
            oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;

        if (newCommand != null)
            newCommand.CanExecuteChanged += HandleCanExecuteChanged;

        HandleCanExecuteChanged(newCommand, EventArgs.Empty);
    }

    private void HandleCanExecuteChanged(object sender, EventArgs args)
    {
        if (Command != null)
            IsEnabled = Command.CanExecute(CommandParameter);
    }

    public ICommand Command
    {
        get { return GetValue(CommandProperty) as ICommand; }
        set { SetValue(CommandProperty, value); }
    }

    public static DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter",
                                    typeof(object), typeof(CommandListBox),
                                    new PropertyMetadata(null));

    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

}

我正在捕捉事件,当列表框中的所选项目发生更改但我不知道如何获取它的值。 你能帮帮我吗?

2 个答案:

答案 0 :(得分:0)

您可以将列表框的SelectedItem属性绑定到ViewModel中的相应属性。

答案 1 :(得分:0)

您的CommandListBox派生自ListBox,它公开了一个SelectionChanged事件,您已经附加到该事件。

SelectionChanged += (sender, e) =>
        {
            if (Command != null && Command.CanExecute(CommandParameter))
                Command.Execute(CommandParameter);
        };

为了获得当前选择的项目,您可以执行以下操作:

  SelectionChanged += (sender, e) =>
            {
                CommandListBox source = sender as CommandListBox; // This is the sender
                if(source != null) // just to be sure
                {
                    var value = source.SelectedItem;
                }    
                if (Command != null && Command.CanExecute(CommandParameter))
                    Command.Execute(CommandParameter);
            };

这有帮助吗?