如何在ObservableCollection的每个项中更改数据?

3

我在XAML中有这样的结构,每个项目都有复选框。

□ Fruits
   □ Apple
   □ Banana
   □ Orange

我的目标是创建一个函数,如果选中了水果的复选框,则会选择所有的水果(全选)。
因此,我在我的复选框的 IsChecked 中绑定了 ViewModel 的函数。
<TreeView
    ItemsSource="{Binding Foods}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type domain:Food}" ItemsSource="{Binding Fruits}">
            <StackPanel Orientation="Horizontal">
                <CheckBox
                    IsChecked="{Binding SelectAll}"
                    />
                <TextBlock Text="   "/>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type domain:Fruit}">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

我的ViewModel是:

private bool _selectAll = false;

public bool SelectAll
{
    get
    {
        return _selectAll;
    }
    set
    {
        foreach (var item in Fruits)
        {
            item.isSelected = true;
        }
    }
}

编辑

public class Food
{
    public string Name { get; set; }
    public ObservableCollection<Fruit> Fruits { get; set; } = new ObservableCollection<Fruit>();
}

public class Fruit
{
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

但是什么都没有发生。

2
你能展示一下在标题中提到的ObservableCollection绑定的位置以及相应的属性吗? - MindSwipe
你的HierarchicalDataTemplate之外是什么? - MindSwipe
请将整个TreeView粘贴到您的项目中,就像它现在所在的位置一样。我仍然收到编译器错误。 - MindSwipe
现在,如果您可以添加属性“食品”和“水果”,以及任何所需的类。 - MindSwipe
水果只是食品集合中的一部分。这是解决问题非常重要的信息。我在这里不是为了假设和解释问题的内容,因为这很容易导致不准确或完全错误的答案。 - MindSwipe
显示剩余2条评论
1个回答

2

我不确定你原本期望的是什么,但根据问题中所给的XAML代码,我甚至没有看到在每个水果名称前面有复选框,所以我需要对XAML进行一些编辑:

<TreeView
    ItemsSource="{Binding Foods}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type domain:Food}" ItemsSource="{Binding Fruits}">
            <StackPanel Orientation="Horizontal">
                <CheckBox
                    IsChecked="{Binding SelectAll}" />
                <TextBlock Text="   " />
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type domain:Fruit}">
            <!-- Here I added the StackPanel and the CheckBox -->
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsSelected}" />
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

之后我进行了一些代码更改,主要是实现了INotifyPropertyChanged。因此,现在Food和Fruit类看起来像这样:

public class Food
{
    public string Name { get; set; }

    public ObservableCollection<Fruit> Fruits { get; set; }

    private bool _selectAll;

    public bool SelectAll
    {
        get => _selectAll;
        set
        {
            _selectAll = value;
            foreach (var f in Fruits)
                f.IsSelected = value;
        }
    }
}

这是水果的样子。
public class Fruit : INotifyPropertyChanged
{
    public string Name { get; set; }

    private bool _isSelected;

    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            _isSelected = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

编辑:在Food上不需要使用INotifyPropertyChanged


你是指 System.ComponentModel.INotifyPropertyChanged 吗? - LindaSingh
1
是的,System.ComponentModel.INotifyPropertyChanged。 - MindSwipe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接