Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.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# WPF TreeView复选框绑定-如何使用复选框填充ViewModel_C#_Wpf_Xaml_Checkbox_Data Binding - Fatal编程技术网

C# WPF TreeView复选框绑定-如何使用复选框填充ViewModel

C# WPF TreeView复选框绑定-如何使用复选框填充ViewModel,c#,wpf,xaml,checkbox,data-binding,C#,Wpf,Xaml,Checkbox,Data Binding,对于如何设置带有绑定的复选框,以确保使用所有选中字段填充ViewModel,我有点困惑。我在底部提供了一些代码和说明 我的Xaml文件称之为TreeView.Xaml: <TreeView x:Name="availableColumnsTreeView" ItemsSource="{Binding Path=TreeFieldData, Mode=OneWay, Converter={StaticResource SortingConverter}

对于如何设置带有绑定的
复选框
,以确保使用所有选中字段填充ViewModel,我有点困惑。我在底部提供了一些代码和说明

我的Xaml文件称之为
TreeView.Xaml

<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
    }
问题:


我想要的行为是,当用户选中一个复选框时,它应该设置
TreeField
IsSelected
属性(它现在就这样做了),但是我想返回到视图模型,并确保将这个特定的
TreeField
添加到
SelectedFields
。我真的不明白
属性changedevent.Invoke的作用以及谁将接收该事件?如何确保
SelectedFields
AddFields()时填充
被调用它有所有已检查的
TreeField
数据实例?

您可以迭代
TreeFieldData
集合中的
TreeFieldData
对象,并将事件处理程序连接到其
属性更改的
事件,然后从
所选字段
集合,例如:

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);
    }
}

PropertyChanged事件的订阅者是视图,因此,如果以编程方式更改IsSelected,则视图知道它需要更新

要将选定的树字段插入列表,您需要将此代码添加到setter中

此外,您还可以定义以下函数,如果您有多个属性,该函数将使通知更容易:

private void NotifyPropertyChange([CallerMemberName] string propertyName = null)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
CallerMemberName属性指示编译器自动插入调用该方法的属性的名称。这个after PropertyChanged是比较not null的缩写

IsSelected的setter可以更改为

set
{
  _isSelected = value;
  if (value) { viewModel.SelectedFields.Add(this); }
  else { viewModel.SelectedFields.Remove(this); }
  NotifyPropertyChange();
}
当然,您需要在ViewModel实例中提供TreeFieldData,例如在构造函数中


我不知道SelectedFields是否在您的视图中有界/显示。如果是,并且希望显示对列表所做的更改,则应将列表更改为ObservableCollection。

我猜MultipleColumnsSelectorVM类有一个“TreeFieldData”属性,该属性返回您在TreeView中看到的TreeFieldData对象列表?@mm8抱歉,是,我现在已经包括了它。@mm8供参考:TreeFieldData属性由一个初始化方法填充,我没有包括这个方法。谢谢,它可以工作,但只适用于“最外面”的节点。每个TreeFieldData节点都有一个子节点列表,因此我必须递归地遍历它,以确保所有字段都附加了PropertyChangedEvent。这有意义吗?我现在正在处理这个问题,在Initialize方法中执行递归。是的,您需要迭代并连接SelectedFields集合中要跟踪的所有项的事件处理程序。是的。这样做会影响性能吗?假设我们有几百块地?它只是真正附加了处理程序,但我不知道附加一个事件处理程序有多贵,而不是那么贵。
private void NotifyPropertyChange([CallerMemberName] string propertyName = null)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
set
{
  _isSelected = value;
  if (value) { viewModel.SelectedFields.Add(this); }
  else { viewModel.SelectedFields.Remove(this); }
  NotifyPropertyChange();
}