开发者

MVVM, Data binding command

开发者 https://www.devze.com 2023-02-18 21:55 出处:网络
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'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)
    {
        _execut开发者_StackOverflow中文版e((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?


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 ?


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

0

精彩评论

暂无评论...
验证码 换一张
取 消