【问题标题】:mvvm confusion with canexecute and binding commandsmvvm 与 canexecute 和 binding 命令混淆
【发布时间】:2013-07-17 19:07:44
【问题描述】:

我很难理解关于这个主题的教程和帖子中的逻辑。我正在尝试在我正在编写的 wpf 应用程序中实现它。

基本上,我使用列表框在列表中显示对象的 ToString,并允许用户通过添加和删除按钮从该列表及其相应的列表框中添加和删除。我遇到的问题是删除按钮的实现。如果没有选择列表框项,我希望禁用该按钮,这是此模式的优点之一。我不知道如何实现该条件。

目前,当我突出显示列表框项目时,该按钮未启用。我想 CanExecuteChanged 事件没有触发。我需要如何更改它?

我的 CommandsHandler 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace TechopsTools
{

    public class CommandHandler : ICommand
    {
        private Action<object> _execute;
        private bool _canExecute;

        public CommandHandler(Action<object> execute)
            : this(execute, true)
        {
        }

        public CommandHandler(Action<object> execute, bool canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }


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

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

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }

}

我的视图模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace TechopsTools
{
    class LogCheckClientViewModel : INotifyPropertyChanged
    {
        private string uri;
        private string response;
        private bool _canRemove;
        private LogConstraints selectedConstraints;

        private ObservableCollection<LogConstraints> constraints;

        public event PropertyChangedEventHandler PropertyChanged;

        public LogConstraints SelectedConstraints
        {
            get
            {
                return selectedConstraints;
            }
            set
            {
                selectedConstraints = value;
                OnPropertyChanged("SelectedConstraints");
            }
        }

        private CommandHandler removeItemCommand;
        public ICommand RemoveItemCommand
        {
            get
            {
                if (removeItemCommand == null)
                    removeItemCommand = new CommandHandler(param => RemoveConstraint(), SelectedConstraints != null);
                return removeItemCommand;
            }
        }

        public string Response 
        {
            get
            {
                return response;
            }
            set
            {
                response = value;
                OnPropertyChanged("Response");
            }
        }

        public string Uri
        {
            get
            {
                return uri;
            }
            set
            {
                uri = value;
                OnPropertyChanged("Uri");
            }
        }

        public ObservableCollection<LogConstraints> Constraints
        {
            get
            {
                return constraints;
            }
            set
            {
                constraints = value;
                OnPropertyChanged("Constraints");
            }
        }

        public LogCheckClientViewModel()
        {
            constraints = new ObservableCollection<LogConstraints>();
        }

        public void AddConstraint()
        {
            NewConstraint newConstraint = new NewConstraint();
            newConstraint.ShowDialog();
            if (newConstraint._vm.constraint != null)
            {
                constraints.Add(newConstraint._vm.constraint);
            }
        }

        private void RemoveConstraint()
        {
            Constraints.Remove(SelectedConstraints);
            OnPropertyChanged("Constraints");
        }

xaml:

<Window x:Class="TechopsTools.LogCheckClient"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TechopsTools"
        Title="LogCheck" Height="453.057" Width="495.986">
    <Grid>
        <TextBox Text="{Binding Response}" HorizontalAlignment="Left" Height="128" Margin="38,212,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="413" VerticalScrollBarVisibility="Auto" IsEnabled="False"/>
        <Label Content="Response" HorizontalAlignment="Left" Margin="38,188,0,0" VerticalAlignment="Top" Width="78" Height="24"/>
        <TextBox Text="{Binding Uri}" HorizontalAlignment="Left" Height="23" Margin="38,26,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="413"/>
        <Label Content="Uri" HorizontalAlignment="Left" Margin="38,0,0,0" VerticalAlignment="Top" Width="78" Height="24"/>
        <Button Content="Add Constraint" HorizontalAlignment="Left" Margin="38,54,0,0" VerticalAlignment="Top" Width="127" Height="56" Click="Add_Click"/>
        <Button x:Name="Submit" Content="Submit Request" HorizontalAlignment="Left" Margin="38,345,0,0" VerticalAlignment="Top" Width="413" Height="70" Click="Submit_Click"/>
        <ListBox SelectedItem="{Binding Path=SelectedConstraints,UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Constraints}" HorizontalAlignment="Left" Height="124" Margin="182,54,0,0" VerticalAlignment="Top" Width="269">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=description}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Command="{Binding RemoveItemCommand}" Content="Remove Constraint" HorizontalAlignment="Left" Margin="38,122,0,0" VerticalAlignment="Top" Width="127" Height="56" />
    </Grid>
</Window>

【问题讨论】:

  • 您最好尝试找到一个为 MVVM 提供支持类的框架。我个人最喜欢的是棱镜。

标签: c# wpf mvvm


【解决方案1】:

您确实需要像使用 Execute 处理程序一样使用 CanExecute 委托。

基本上现在您正在检查它是否可以在首次访问 RemoveItemCommand 时执行。但它只是一直保持这个值。

如果您传入一个具有相同条件的委托(可能添加一个空列表,而不仅仅是一个空列表),我敢打赌它会起作用。

换句话说,在你的 CommandHandler 中,改变

private bool _canExecute;

private Func<bool,object> _canExecute;

改变

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

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

然后在您的 ViewModel 中进行更改

removeItemCommand = new CommandHandler(param => RemoveConstraint(), 
                                       SelectedConstraints != null);

removeItemcommand = new CommandHandler(param => RemoveConstraint(), 
                                       param => SelectedConstraints != null);

(请注意,这可能不是完全正确的代码,因为我只是徒手写的,但希望你明白这一点)

【讨论】:

  • 我真的不知道委托是如何工作的,并且您建议的 CanExecute() 中的更改给了我错误“Delegate Func has some invalid arguments” 另外,您能解释一下原因吗在这里使用代表可以解决我的问题吗?
  • 基本上正在发生的事情是你正在设置一个函数来告诉CommandHandler如何检查它是否可以执行。最初,您只是传递一次 true 或 false 并且该值卡住了。现在,每次调用 CanExecute() 时,它都会调用您传入的函数并重新执行实际检查,找到一个“新鲜”的新真或假值。
【解决方案2】:

我认为这件事可以在你的 XAML 文件中完成,只需使用 DataTrigger。

如果这个解决方案能让你满意,请写评论告诉我,我会给你一些代码。

最好的问候

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多