0

MVVMパターンを使用して観察可能なコレクションにバインドされているスポーツのチェックボックスリストがあります。ユーザーは好きなスポーツをいくつでも選択できます。[OK]ボタンを押すと、選択したスポーツをメッセージボックスに表示する必要があります(質問のためにコードを簡略化しています)。

[OK]ボタンは、1つ以上のスポーツが選択されている場合にのみ有効にする必要があります。現時点では、これは機能していません。ボタンの有効化/無効化は、を使用IsValidして実行されます。チェックボックスの1つがチェックされるたびにこのメソッドを実行する方法はありますか。 ?

<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

または、作成された強い結合を回避したい場合は、に実装INotifyPropertyChangedして、への変更をリッスンListHelperさせることができます。MainViewModelIsChecked

于 2012-05-07T10:07:17.400 に答える
0

問題の理由は、PRISMDelegateCommandに再クエリのサポートが含まれていないためだと思います。この問題の適切な回避策は、このサイト 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();

checkbok IsCheckedセッターのセッターから:

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

コマンドへの強い参照を保持する必要はありません。少なくとも.NET4.0から利用できます。

于 2016-05-27T06:41:08.600 に答える