3

I have a this structure in XAML where every item has checkbox.

□ Fruits
   □ Apple
   □ Banana
   □ Orange

My goal is to have a function that if Fruit's checkbox is checked, it will check all (select all) fruits.

So I am binding my ViewModel's function in my Checkbox's IsChecked.

<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>

My ViewModel is:

private bool _selectAll = false;

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

Edit

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

But nothing's happening.

LindaSingh
  • 84
  • 1
  • 13
  • 2
    Can you show us where you're binding on to the ObservableCollection mentioned in the title, as well as the corresponding property? – MindSwipe Sep 25 '19 at 07:23
  • And what's outside your HierarchicalDataTemplate? – MindSwipe Sep 25 '19 at 07:39
  • Plese add every line of XAML necessary to display what you want to display to your question. I am getting compiler errors thrown my way when trying to reproduce this, even with the DataTemplate and TextBlock – MindSwipe Sep 25 '19 at 07:48
  • Please just copy and paste the entire TreeView exactly as it is inside your Project. I am still getting compiler errors – MindSwipe Sep 25 '19 at 07:53
  • Now if you could just add the Properties "Foods" and "Fruits" as well as any needed classes – MindSwipe Sep 25 '19 at 08:00
  • "Fruits is just a collection in Foods" This is quite important information for the problem. I'm not here to assume and interpret content of questions, as this can easily lead to inaccurate/ plain wrong answers – MindSwipe Sep 25 '19 at 08:06
  • @MindSwipe, see edit. – LindaSingh Sep 25 '19 at 08:14

1 Answers1

2

I'm not entirely sure what you were expecting, but with the XAML given in the Question I didn't even have check boxes in front of the individual Fruit names, so I had to edit the XAML a little:

<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>

After that I did some code changes, mainly I just implemented INotifyPropertyChanged. So the Food and Fruit class look like this now:

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

And Fruit like this

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

Edit: INotifyPropertyChanged isn't needed on Food

MindSwipe
  • 7,193
  • 24
  • 47