0

我有一个使用 MVVM 模式绑定到可观察集合的运动复选框列表。用户可以选择他/她喜欢的任意数量的运动,当按下 OK 按钮时,所选运动必须显示在消息框中(为了问题而简化了代码)。

The OK button must be enabled only if one or more sports have been selected, at the moment this is not working.The enabling\disabling of the button is done using IsValid, is there any way to execute this method everytime one of the checkboxes is checked ?

我不能使用<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;}
        }
    }
}
4

4 回答 4

1

当复选框被选中/取消选中时,您必须表示NewCommand(由 决定)的可用性发生变化。IsValid你必须这样称呼:

NewCommand.RaiseCanExecuteChanged();

每当ListHelper.IsChecked更新。你必须想出一个很好的方法来把它们连接在一起。您有几个选项,但最直接的可能是提供ListHelper一个参考,以MainViewModel允许它在视图模型上调用适当的方法。

或者,如果您想避免创建的强耦合,您可以实现INotifyPropertyChangedinListHelper并让MainViewModel监听IsChecked.

于 2012-05-07T10:07:17.400 回答
0

我认为您的问题的原因是 PRISM DelegateCommand 不包括重新查询支持。此站点http://compositewpf.codeplex.com/discussions/44750?ProjectName=compositewpf描述了此问题的适当解决方法

于 2012-05-07T10:39:52.453 回答
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));
            }
        }
    }
于 2012-05-07T11:33:47.677 回答
0

我有最好的解决方案:打电话

CommandManager.InvalidateRequerySuggested();

从您的支票 IsChecked 二传手的二传手:

    public bool IsChecked 
    {
        get { return isChecked; }
        set 
        {
            isChecked = value;
            CommandManager.InvalidateRequerySuggested();
        }
    }

无需对命令进行强引用。至少可从 .NET 4.0 获得。

于 2016-05-27T06:41:08.600 回答