MVVM,数据绑定命令

发布于 2024-10-22 22:21:52 字数 3547 浏览 2 评论 0原文

我开始在 Silverlight 中使用带有 MVVM 模式的数据绑定。我有一个问题。 我有一个列表框,当我选择一项时,视图模型中的一个属性必须更改它的值。我实现了 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); }
    }

}

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

I've started using databinding with MVVM pattern in Silverlight. There's one problem for me.
I have a listbox, when I select an item there one property in the View-Model have to change it's value. I implemented DelegateCommand and made custom CommandListBox class as follows

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

}

I'm catching the event, when the selected item in listbox is changed but I don't know how to take it's value.
Could you help me please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

〆一缕阳光ご 2024-10-29 22:21:52

您的 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);
            };

这有帮助吗?

Your CommandListBox derives from a ListBox, it exposes a SelectionChanged event, you're attaching to that event already.

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

In order to obtain the currently selected item you can do something like this :

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

Does this help ?

幻梦 2024-10-29 22:21:52

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

You can bind your listbox's SelectedItem property to an appropriate property in your ViewModel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文