我有一个sports的复选框列表,它使用MVVM模式绑定到一个可观察的集合。 用户可以选择他喜欢的任意数量的运动,当按下确定按钮时,必须在消息框中显示所选的运动(为了问题简化了代码)。
只有在选择了一项或多项运动时,必须启用“确定”按钮,此时此功能不起作用。使用IsValid
启用\禁用该按钮,是否有任何方法可以执行此操作每次检查其中一个复选框时的方法?
我无法使用<Button IsEnabled="{Binding ElementName=checkBox1, Path=IsChecked}" />
,因为开发代码中有多个属性需要在使用按钮之前检查其有效性,因为我使用的是Prism,所以这个应该使用如果可能的话,IsValid
方法。
XAML
<Window x:Class="WpfApplication13.MVVM.ComboboxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
xmlns:local="WpfApplication13.MVVM" Title="MainWindow" Height="170" Width="507">
<Grid>
<ListBox ItemsSource="{Binding Sports}" Name="lbModules" ScrollViewer.VerticalScrollBarVisibility="Visible"
Height="72" Margin="3" VerticalAlignment="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Text}" IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Name="chkModules" Margin="0,5,0,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Height="27" Width="70" Margin="3,80,3,3" VerticalAlignment="Top"
Content="OK" HorizontalAlignment="Left"
prism:Click.Command="{Binding Path=NewCommand}"></Button>
</Grid>
</Window>
查看模型
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using Microsoft.Practices.Composite.Presentation.Commands;
namespace WpfApplication13.MVVM
{
public class MainWindowViewModel : INotifyPropertyChanged
{
public DelegateCommand<object> NewCommand { get; protected set; }
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<ListHelper> modules = new ObservableCollection<ListHelper>();
public ObservableCollection<ListHelper> Sports
{
get { return modules; }
set { modules = value; OnPropertyChanged("Sports"); }
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
NewCommand.RaiseCanExecuteChanged();
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public MainWindowViewModel()
{
ListHelper item1 = new ListHelper() { Text = "Footbal", IsChecked = false };
ListHelper item2 = new ListHelper() { Text = "Boxing", IsChecked = false };
ListHelper item3 = new ListHelper() { Text = "Basketball", IsChecked = false };
Sports.Add(item1);
Sports.Add(item2);
Sports.Add(item3);
NewCommand = new DelegateCommand<object>(NewTemplate, IsValid);
}
private bool IsValid(object parameter)
{
//TODO:This method must execute EVERYTIME any of the checkboxes are checked\unchecked.(currently not happening)
//The return value then determines the enabled state of the button.
return Sports.Any(e => e.IsChecked);
}
private void NewTemplate(object parameter)
{
//Display a list of selected sports
string sports = String.Empty;
Sports.Where(e => e.IsChecked).ToList().ForEach(c => sports += c.Text + " ");
MessageBox.Show(sports);
}
}
public class ListHelper
{
public String Text { get; set; }
private bool isChecked = false;
public Boolean IsChecked
{
get { return isChecked; }
//The setter is executed everytime the checkbox is checked
set {isChecked = value;}
}
}
}
答案 0 :(得分:1)
当选中/取消选中复选框时,您必须发出NewCommand
(由IsValid
确定)的可用性变化信号。你必须这样称呼:
NewCommand.RaiseCanExecuteChanged();
每当ListHelper.IsChecked
更新时。你必须想出一个很好的方法来连接它。您有几个选项,但最直接的可能是ListHelper
提供MainViewModel
的引用,允许它在视图模型上调用适当的方法。
或者,如果您想避免创建强耦合,可以在INotifyPropertyChanged
中实现ListHelper
,并让MainViewModel
侦听对IsChecked
的更改。
答案 1 :(得分:0)
我认为您的问题的原因是,PRISM DelegateCommand不包括requery支持。此站点描述了此问题的正确解决方法 http://compositewpf.codeplex.com/discussions/44750?ProjectName=compositewpf
答案 2 :(得分:0)
必须更改ListHelper类,如下所示。按钮验证现在按预期执行:
public class ListHelper : INotifyPropertyChanged
{
private DelegateCommand<object> _command = null;
private string _propertyName = String.Empty;
public ListHelper(DelegateCommand<object> command,string propertyName)
{
_command = command;
propertyName = _propertyName;
}
public event PropertyChangedEventHandler PropertyChanged;
public String Text { get; set; }
private bool isChecked = false;
public Boolean IsChecked
{
get { return isChecked; }
//The setter is executed everytime the checkbox is checked
set
{
isChecked = value;
OnPropertyChanged(_propertyName);
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null && _command != null)
{
_command.RaiseCanExecuteChanged();
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
答案 3 :(得分:0)
我有最好的解决方案:致电
rand(1, 1000000);
来自你的checkbok IsChecked setter的设定者:
CommandManager.InvalidateRequerySuggested();
无需强烈引用该命令。至少可以从.NET 4.0获得。