Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何处理MVVM模式中的多个复选框?_C#_Wpf_Xaml_Mvvm_Checkbox - Fatal编程技术网

C# 如何处理MVVM模式中的多个复选框?

C# 如何处理MVVM模式中的多个复选框?,c#,wpf,xaml,mvvm,checkbox,C#,Wpf,Xaml,Mvvm,Checkbox,WPF中的绑定复选框是一个常见问题,但我仍然没有找到初学者容易理解的示例代码。我在WPF中有复选框列表来选择最喜爱的运动的名称。在我的例子中,复选框的数量是静态的。有人能告诉我如何实现这个问题的ViewModel吗 FavoriteSportsView.xaml: <StackPanel Height="50" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150"> <CheckBox Is

WPF中的绑定复选框是一个常见问题,但我仍然没有找到初学者容易理解的示例代码。我在WPF中有复选框列表来选择最喜爱的运动的名称。在我的例子中,复选框的数量是静态的。有人能告诉我如何实现这个问题的ViewModel吗

FavoriteSportsView.xaml:

  <StackPanel Height="50" HorizontalAlignment="Left" VerticalAlignment="Top" 
  Width="150">

  <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"  
  Command="{Binding Path=SportsResponseCommand}" 
  CommandParameter="Football" 
  Content="Football" 
  Margin="5" />

  <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" 
  Command="{Binding Path=SportsResponseCommand}" 
  CommandParameter="Hockey" 
  Content="Hockey" 
  Margin="5" />

  <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" 
  Command="{Binding Path=SportsResponseCommand}" 
  CommandParameter="Golf" 
  Content="Golf" 
  Margin="5" />
  </StackPanel>
我不确定如何在上述ViewModel中执行以下操作: 1.如何实现单个方法来处理所有选项? 2.如何检测每个复选框以查看是否选中 3.如何使用CommandParameter?
4.如何正确实现SportsResponseCommand

如果您只想在检查
时更新ViewModel中的属性,请将检查的绑定替换为ViewModel中的布尔属性,该属性在其“集合”上引发
NotifyPropertyChanged

现在,如果您想在每次检查3个复选框之一时执行操作:

首先,将CommandParameter替换为
“{Binding RelativeSource={RelativeSource Mode=Self}}”

在ViewModel(应实现INotifyPropertyChanged)中,创建一个ICommand(SportsResponseCommand),该命令在参数中包含一个复选框

在命令的方法中,检查复选框的内容,以及“IsChecked”属性,然后对它们进行处理


如果您还有其他问题,请告诉我。

如果您只想在检查
时更新ViewModel中的属性,请将检查的绑定替换为ViewModel中的布尔属性,该属性在其“集合”上引发
NotifyPropertyChanged

现在,如果您想在每次检查3个复选框之一时执行操作:

首先,将CommandParameter替换为
“{Binding RelativeSource={RelativeSource Mode=Self}}”

在ViewModel(应实现INotifyPropertyChanged)中,创建一个ICommand(SportsResponseCommand),该命令在参数中包含一个复选框

在命令的方法中,检查复选框的内容,以及“IsChecked”属性,然后对它们进行处理


如果您还有其他问题,请告诉我。

您的视图模型应该如下所示:

public class MyViewModel : INotifyPropertyChanged
{
    //INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    //bindable property
    private bool _football;
    public bool Football
    {
        get { return _football; }
        set
        {
            if (value != _football)
            {
                _football = value;
                this.OnPropertyChanged("Football");
            }
        }
    }

    //... and the same for Golf and Hockey
}
然后通过设置
DataContext
属性将视图模型与视图关联起来(这很可能在
窗口中
UserControl
代码隐藏中,尽管有很多方法可以实现)

最后,更新绑定,使其看起来像:

<CheckBox IsChecked="{Binding Football, Mode=TwoWay}"  
 Content="Football" 
 Margin="5" />

<CheckBox IsChecked="{Binding Golf, Mode=TwoWay}"   
 Content="Football" 
 Margin="5" />


最后,您不需要绑定
命令
属性-您只需编写需要在视图模型的属性设置程序中运行的任何代码。

您的视图模型应该如下所示:

public class MyViewModel : INotifyPropertyChanged
{
    //INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    //bindable property
    private bool _football;
    public bool Football
    {
        get { return _football; }
        set
        {
            if (value != _football)
            {
                _football = value;
                this.OnPropertyChanged("Football");
            }
        }
    }

    //... and the same for Golf and Hockey
}
然后通过设置
DataContext
属性将视图模型与视图关联起来(这很可能在
窗口中
UserControl
代码隐藏中,尽管有很多方法可以实现)

最后,更新绑定,使其看起来像:

<CheckBox IsChecked="{Binding Football, Mode=TwoWay}"  
 Content="Football" 
 Margin="5" />

<CheckBox IsChecked="{Binding Golf, Mode=TwoWay}"   
 Content="Football" 
 Margin="5" />


最后,您不应该真正需要绑定
命令
属性-您只需编写在视图模型的属性设置器中运行所需的任何代码。

您可以使用此命令指定视图模型

 //for the view

partial class MainView:Window
 {
         InitializeComponent();
         this.DataContext=new MainViewModel();

 }

//ViewModel Code

public class MainViewModel: INotifyPropertyChanged
{
  //INotifyPropertyChanged implementation
  public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

//bindable property
private bool _football;
public bool Football
{
    get { return _football; }
    set
    {
        if (value != _football)
        {
            _football = value;
            this.OnPropertyChanged("Football");
        }
    }
}

//... and the same for Golf and Hockey
}`
然后可以在XAML中实现绑定,如下所示


您可以使用以下命令指定视图模型

 //for the view

partial class MainView:Window
 {
         InitializeComponent();
         this.DataContext=new MainViewModel();

 }

//ViewModel Code

public class MainViewModel: INotifyPropertyChanged
{
  //INotifyPropertyChanged implementation
  public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

//bindable property
private bool _football;
public bool Football
{
    get { return _football; }
    set
    {
        if (value != _football)
        {
            _football = value;
            this.OnPropertyChanged("Football");
        }
    }
}

//... and the same for Golf and Hockey
}`
然后可以在XAML中实现绑定,如下所示


我强烈建议您阅读此
我在下面描述了一个解决方案,我试图不修改您的XAML代码,但这不是唯一的方法(或最佳方法),而是包含所有必要的元素

第一步你们需要你们的模型,我称之为模型运动

    public class Model_Sport : INotifyPropertyChanged
    {
        #region  Constructor

        public Model_Sport(string name, ICommand command)
        {
            Name = name;
            SportsResponseCommand = command;
        }

        #endregion

        static readonly PropertyChangedEventArgs _NameEventArgs = new PropertyChangedEventArgs("Name");
        private string _Name = null;
        public string Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                OnPropertyChanged(_NameEventArgs);
            }
        }

        static readonly PropertyChangedEventArgs _SportsResponseCommandEventArgs = new PropertyChangedEventArgs("SportsResponseCommand");
        private ICommand _SportsResponseCommand = null;
        public ICommand SportsResponseCommand
        {
            get { return _SportsResponseCommand; }
            set
            {
                _SportsResponseCommand = value;
                OnPropertyChanged(_SportsResponseCommandEventArgs);
            }
        }

        static readonly PropertyChangedEventArgs _IsCheckedEventArgs = new PropertyChangedEventArgs("IsChecked");
        private bool _IsChecked = false;
        public bool IsChecked
        {
            get { return _IsChecked; }
            set
            {
                _IsChecked = value;
                OnPropertyChanged(_IsCheckedEventArgs);
            }
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, eventArgs);
            }
        }

        #endregion
    }
现在您需要一种方法来委托您的命令“SportsResponseCommand”,DelegateCommand对象将帮助您这样做

    public class DelegateCommand : ICommand
    {
        private readonly Action<object> _ExecuteMethod;
        private readonly Func< object, bool> _CanExecuteMethod;

        #region Constructors

        public DelegateCommand(Action<object>executeMethod, Func<object, bool> canExecuteMethod)
        {
            if (null == executeMethod)
            {
                throw new ArgumentNullException("executeMethod", "Delegate Command Delegates Cannot Be Null");
            }

            _ExecuteMethod = executeMethod;
            _CanExecuteMethod = canExecuteMethod;

        }

        public DelegateCommand(Action<object>executeMethod) : this(executeMethod, null) { }

        #endregion


        #region Methods

        public bool CanExecute(object parameter)
        {
            if (_CanExecuteMethod == null) return true;
            return _CanExecuteMethod(parameter);
        }

        public void Execute(object parameter)
        {
            if (_ExecuteMethod == null) return;
            _ExecuteMethod(parameter);
        }

        bool ICommand.CanExecute(object parameter)
        {
            return CanExecute(parameter);
        }

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

        void ICommand.Execute(object parameter)
        {
            Execute(parameter);
        }

        #endregion

    }
然后在XAML中

    <StackPanel  HorizontalAlignment="Left" VerticalAlignment="Top" >

        <CheckBox DataContext="{Binding Path=Sports[Football]}"
            IsChecked="{Binding IsChecked, Mode=TwoWay}"   
                    Command="{Binding Path=SportsResponseCommand}"  
                    CommandParameter="Football"    
                    Content="Football"   
                    Margin="5" />

        <CheckBox DataContext="{Binding Path=Sports[Hockey]}"
            IsChecked="{Binding IsChecked, Mode=TwoWay}"  
            Command="{Binding Path=SportsResponseCommand}"    
            CommandParameter="Hockey"    
            Content="Hockey"   
            Margin="5" />

        <CheckBox DataContext="{Binding Path=Sports[Golf]}" IsChecked="{Binding IsChecked, Mode=TwoWay}" 
                    Command="{Binding Path=SportsResponseCommand}"
                    CommandParameter="Golf"   
                    Content="Golf" 
                    Margin="5" />
    </StackPanel>

我强烈建议您阅读此
我在下面描述了一个解决方案,我试图不修改您的XAML代码,但这不是唯一的方法(或最佳方法),而是包含所有必要的元素

第一步你们需要你们的模型,我称之为模型运动

    public class Model_Sport : INotifyPropertyChanged
    {
        #region  Constructor

        public Model_Sport(string name, ICommand command)
        {
            Name = name;
            SportsResponseCommand = command;
        }

        #endregion

        static readonly PropertyChangedEventArgs _NameEventArgs = new PropertyChangedEventArgs("Name");
        private string _Name = null;
        public string Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                OnPropertyChanged(_NameEventArgs);
            }
        }

        static readonly PropertyChangedEventArgs _SportsResponseCommandEventArgs = new PropertyChangedEventArgs("SportsResponseCommand");
        private ICommand _SportsResponseCommand = null;
        public ICommand SportsResponseCommand
        {
            get { return _SportsResponseCommand; }
            set
            {
                _SportsResponseCommand = value;
                OnPropertyChanged(_SportsResponseCommandEventArgs);
            }
        }

        static readonly PropertyChangedEventArgs _IsCheckedEventArgs = new PropertyChangedEventArgs("IsChecked");
        private bool _IsChecked = false;
        public bool IsChecked
        {
            get { return _IsChecked; }
            set
            {
                _IsChecked = value;
                OnPropertyChanged(_IsCheckedEventArgs);
            }
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, eventArgs);
            }
        }

        #endregion
    }
现在您需要一种方法来委托您的命令“SportsResponseCommand”,DelegateCommand对象将帮助您这样做

    public class DelegateCommand : ICommand
    {
        private readonly Action<object> _ExecuteMethod;
        private readonly Func< object, bool> _CanExecuteMethod;

        #region Constructors

        public DelegateCommand(Action<object>executeMethod, Func<object, bool> canExecuteMethod)
        {
            if (null == executeMethod)
            {
                throw new ArgumentNullException("executeMethod", "Delegate Command Delegates Cannot Be Null");
            }

            _ExecuteMethod = executeMethod;
            _CanExecuteMethod = canExecuteMethod;

        }

        public DelegateCommand(Action<object>executeMethod) : this(executeMethod, null) { }

        #endregion


        #region Methods

        public bool CanExecute(object parameter)
        {
            if (_CanExecuteMethod == null) return true;
            return _CanExecuteMethod(parameter);
        }

        public void Execute(object parameter)
        {
            if (_ExecuteMethod == null) return;
            _ExecuteMethod(parameter);
        }

        bool ICommand.CanExecute(object parameter)
        {
            return CanExecute(parameter);
        }

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

        void ICommand.Execute(object parameter)
        {
            Execute(parameter);
        }

        #endregion

    }
然后在XAML中

    <StackPanel  HorizontalAlignment="Left" VerticalAlignment="Top" >

        <CheckBox DataContext="{Binding Path=Sports[Football]}"
            IsChecked="{Binding IsChecked, Mode=TwoWay}"   
                    Command="{Binding Path=SportsResponseCommand}"  
                    CommandParameter="Football"    
                    Content="Football"   
                    Margin="5" />

        <CheckBox DataContext="{Binding Path=Sports[Hockey]}"
            IsChecked="{Binding IsChecked, Mode=TwoWay}"  
            Command="{Binding Path=SportsResponseCommand}"    
            CommandParameter="Hockey"    
            Content="Hockey"   
            Margin="5" />

        <CheckBox DataContext="{Binding Path=Sports[Golf]}" IsChecked="{Binding IsChecked, Mode=TwoWay}" 
                    Command="{Binding Path=SportsResponseCommand}"
                    CommandParameter="Golf"   
                    Content="Golf" 
                    Margin="5" />
    </StackPanel>


Beat me to it,但是您应该从复选框XAMLBeat me to it中删除Command/CommandParameter,但是您应该从复选框XAMLIs中删除Command/CommandParameter,使用复选框列表是您的一个选项吗?使用复选框列表是您的一个选项吗?感谢您Fred Jand的详细实施。我已经读到,如果不在模型中实现INotifyPropertyChanged,这将是一件好事。你同意这种说法吗?您对使用RelayCommand而不是DelegateCommand有什么看法?您看到任何缺点了吗?实际上RelayCommand和DelgateCommad几乎是相同的实体RelayCommand是Microsoft复合应用程序库中DelegateCommand的简化变体。如果你想要更真实的delegatecommand实现,我在这里放的实际上是一个RelayCommand。请注意,它们只是名称,并且在这几年中开发了这两个命令的不同变体!关键是他们有完全相同的概念。您可以创建自己版本的delegatecommand或relaycommand!正如我在本例中所做的:)关于“INotifyPropertyChanged”,它取决于应用程序!如果模型表示独立更改的内容,并且对应用程序的其他部分(viewmodel除外)有副作用,则最好在模型中更改InotifyProperty。但如果