2017-03-08 5 views
1

CheckBoxにViewModelにすべてのチェックされたフィールドが確実に入力されるようにバインディングを設定する方法について、少し混乱します。私はいくつかのコードと説明を下部に記載しています。WPF TreeView CheckBox Binding - ViewModelにチェックボックスを設定する方法

私のXAMLファイルはのはTreeView.xamlそれを呼びましょう:TreeView.xaml.cs

public partial class MultipleColumnsSelectorView : UserControl 
{ 
    public MultipleColumnsSelectorView() 
    { 
     InitializeComponent(); 
    } 

    private MultipleColumnsSelectorVM Model 
    { 
     get { return DataContext as MultipleColumnsSelectorVM; } 
    } 
} 

<TreeView x:Name="availableColumnsTreeView"   
      ItemsSource="{Binding Path=TreeFieldData, Mode=OneWay, Converter={StaticResource SortingConverter}, ConverterParameter='DisplayName.Text'}"> 

    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate x:Uid="HierarchicalDataTemplate_1" ItemsSource="{Binding Path=Children, Mode=OneWay, Converter={StaticResource SortingConverter}, ConverterParameter='DisplayName.Text'}"> 
      <CheckBox VerticalAlignment="Center" IsChecked="{Binding IsSelected, Mode=TwoWay}"> 
       <TextBlock x:Uid="TextBlock_1" Text="{Binding DisplayName.Text, Mode=OneWay}" /> 
      </CheckBox>    
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

"の背後にあるコードは" ViewModelにはMultipleColumnsSelectorVM(のみ関連のものを含めることを試みた):

public partial class MultipleColumnsSelectorVM : ViewModel, IMultipleColumnsSelectorVM 
{ 
    public ReadOnlyCollection<TreeFieldData> TreeFieldData 
    { 
     get { return GetValue(Properties.TreeFieldData); } 
     set { SetValue(Properties.TreeFieldData, value); } 
    } 

    public List<TreeFieldData> SelectedFields 
    { 
     get { return GetValue(Properties.SelectedFields); } 
     set { SetValue(Properties.SelectedFields, value); } 
    } 

    private void AddFields() 
    { 
     //Logic which loops over SelectedFields and when done calls a delegate which passes 
     //the result to another class. This works, implementation hidden 
    } 

モデルTreeFieldData

public class TreeFieldData : INotifyPropertyChanged 
{  
    public event PropertyChangedEventHandler PropertyChanged; 
    public IEnumerable<TreeFieldData> Children { get; private set; } 
    private bool _isSelected; 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      if (PropertyChanged != null) 
       PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsSelected")); 
     } 
    } 
} 

問題:

私が望む行動は、ユーザーがチェックボックスをチェックしたときに、それはTreeFieldIsSelectedプロパティを設定する必要がある(それは今のことを行います)が、その後、私はしたいですViewModelに戻り、TreeFieldSelectedFieldsに追加されていることを確認してください。 PropertyChangedEvent.Invokeが何を行い、誰がそのイベントを受け取るのか本当に分かりません。 SelectedFieldsにデータが入力されるようにするには、AddFields()が呼び出されたときに、チェックされたデータインスタンスがすべてTreeFieldであることを確認しますか?

+0

MultipleColumnsSelectorVMクラスには、TreeViewに表示されるTreeFieldDataオブジェクトのリストを返す "TreeFieldData"プロパティがあると思いますか? – mm8

+0

@ mm8申し訳ありません、私は今それを含めました。 – DSF

+0

@ mm8 FYI:TreeFieldDataプロパティには、含まれていないInitializeメソッドが設定されています。 – DSF

答えて

2

あなたは例えば、TreeFieldDataコレクションにTreeFieldDataオブジェクトを反復処理し、そのPropertyChangedイベントにイベントハンドラをフックして、追加/ SelectedFieldsコレクションから選択/非選択項目を削除できます。

public MultipleColumnsSelectorVM() 
{ 
    Initialize(); 

    //do this after you have populated the TreeFieldData collection 
    foreach (TreeFieldData data in TreeFieldData) 
    { 
     data.PropertyChanged += OnPropertyChanged; 
    } 
} 

private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "IsSelected") 
    { 
     TreeFieldData data = sender as TreeFieldData; 
     if (data.IsSelected && !SelectedFields.Contains(data)) 
      SelectedFields.Add(data); 
     else if (!data.IsSelected && SelectedFields.Contains(data)) 
      SelectedFields.Remove(data); 
    } 
} 
+0

ありがとうございますが、「最外」のノードだけが動作します。 TreeFieldDataノードごとに子供のリストもありますので、すべてのフィールドにPropertyChangedEventが添付されていることを確認するために、再帰的にループする必要があります。それが理にかなっていれば?私はこれで、初期化メソッドで再帰をやっています。 – DSF

+0

はい、SelectedFieldsコレクションで追跡したいすべてのアイテムのイベントハンドラを繰り返し処理して接続する必要があります。 – mm8

+0

はい。これを行うパフォーマンスが悪いことはありますか?何百もの畑があるとしますか?それは本当にハンドラーを添付しているだけですが、私はどのくらいの高価なのかわかりません – DSF

0

PropertyChangedイベントのサブスクライバはビューであるため、IsSelectedをプログラムによって変更すると、ビューは更新する必要があることが分かります。

リストに選択したTreeFieldを挿入するには、このコードをセッターに追加します。

private void NotifyPropertyChange([CallerMemberName] string propertyName = null) 
{ 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

CallerMemberName属性が自動的にメソッドを呼び出し、プロパティの名前を挿入するようにコンパイラに指示します。

また、あなたは多くのプロパティを持っている場合ははるかに容易に通知する次の関数を定義することができます。 ? PropertyChangedがnullとの比較の省略形になった後。

IsSelectedのセッターは、

あなたは、例えば、ViewModelにインスタンスにTreeFieldDataを提供する必要があるだろう。もちろん、
set 
{ 
    _isSelected = value; 
    if (value) { viewModel.SelectedFields.Add(this); } 
    else { viewModel.SelectedFields.Remove(this); } 
    NotifyPropertyChange(); 
} 

に変更することができますコンストラクタで

SelectedFieldsが表示されているかどうかわかりません。はいの場合、リストに加えられた変更を表示するには、List to ObservableCollectionを変更する必要があります。

関連する問題