WPF label not updating value on the UI

asked 2020-05-04T05:30:35.5+00:00
abijith gowda 61 Reputation points

Hi All,
I am currently working on a C# WPF application. The UI contains a tree view with checkboxes. I need a label on the UI to update the number of checked checkboxes. However, even though i get the value and try to update the UI, the 'Property Changed' from the INotifyPropertyChanged is coming as null and preventing the UI from being updated.

I have attached the code. The checkbox in question is the IsChildChecked checkbox and the Label that needs to be updated is the SelectedDevicesCount. The constants.counter is a public static variable which holds on to the value of checked checkboxes.7815-label-and-checkbox-issue.txt
Can anyone please help me on this??

Thank you in advance!!

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,169 questions
{count} votes

Accepted answer
  1. answered 2020-05-04T08:24:59.777+00:00
    Peter Fleischer (Freelancer) 17,386 Reputation points

    Hi; you calculate SelectedCount in ViewModel like in following demo:

    <Window x:Class="WpfApp1.Window35"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp35"
            mc:Ignorable="d"
            Title="Window35" Height="450" Width="800">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
        <Style x:Key="HighlightingTextStyle" TargetType="Label">
          <Setter Property="FontStyle" Value="Italic"/>
        </Style>
      </Window.Resources>
    
      <Grid DataContext="{StaticResource vm}">
        <StatusBar VerticalAlignment="Top">
          <Label Content="Selected Devices:" Margin="1,1,0,1"/>
          <Label Content="{Binding SelectedDevicesCount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </StatusBar>
        <TreeView ItemsSource="{Binding TreeViewDataCollection}" Margin="0 40 0 0">
          <TreeView.Resources>
            <HierarchicalDataTemplate ItemsSource="{Binding HostGroupName}" DataType="{x:Type local:RootNameList}">
              <StackPanel Orientation="Horizontal">
                <Label Style="{StaticResource HighlightingTextStyle}" Content="{Binding RootSubnet}"/>
              </StackPanel>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Host}" DataType="{x:Type local:HostGroup}">
              <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsParentChecked}" IsThreeState="True"/>
                <Label Style="{StaticResource HighlightingTextStyle}" Content="{Binding GroupName}" Tag="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
              </StackPanel>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:HostName}">
              <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChildChecked}"/>
                <Label Style="{StaticResource HighlightingTextStyle}" Content="{Binding Host}" Tag="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
              </StackPanel>
            </HierarchicalDataTemplate>
          </TreeView.Resources>
        </TreeView>
      </Grid>
    </Window>
    

    Classes:

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    
    
    namespace WpfApp35
    {
      public class ViewModel : BaseClass
      {
        public ViewModel()
        {
          LoadData();
          SetHandler();
          cvs.Source = col;
        }
        private void SetHandler()
        {
          foreach (var rnl in col)
            foreach (var hg in rnl.HostGroupName)
            {
              hg.SetHandler();
              hg.PropertyChanged += Hg_PropertyChanged;
            }
        }
    
        private void Hg_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          SelectedDevicesCount = 0;
          foreach (var rnl in col)
            foreach (var hg in rnl.HostGroupName) SelectedDevicesCount += hg.SelectedCount;
          OnPropertyChanged(nameof(SelectedDevicesCount));
        }
    
        private void LoadData()
        {
          for (int i = 1; i < 10; i++)
          {
            var rnl = new RootNameList { RootSubnet = $"RootSubnet{i}" };
            for (int k = 0; k < 10; k++)
            {
              var hg = new HostGroup { GroupName = $"GroupName {k + i * 10}" };
              rnl.HostGroupName.Add(hg);
              for (int l = 0; l < 10; l++)
              {
                var h = new HostName() { Host = $"Host {l}" };
                hg.Host.Add(h);
              }
            }
            col.Add(rnl);
          }
        }
    
        public int SelectedDevicesCount { get; set; }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<RootNameList> col = new ObservableCollection<RootNameList>();
    
        public ICollectionView TreeViewDataCollection { get => cvs.View; }
      }
    
      public class RootNameList
      {
        public string RootSubnet { get; set; }
        public List<HostGroup> HostGroupName { get; set; } = new List<HostGroup>();
      }
    
      public class HostGroup : BaseClass
      {
    
        private bool? _IsParentChecked = false;
        public bool? IsParentChecked
        {
          get => this._IsParentChecked;
          set
          {
            if (!value.HasValue) value = false;
            this._IsParentChecked = value;
            foreach (var h in Host) h.IsChildChecked = value.Value;
            OnPropertyChanged();
          }
        }
        public string GroupName { get; set; }
        public List<HostName> Host { get; set; } = new List<HostName>();
    
        public void SetHandler()
        {
          foreach (var hn in Host) hn.PropertyChanged += h_PropertyChanged;
        }
    
        public int SelectedCount { get; set; } = 0;
    
        internal void h_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          int iFalse = 0;
          SelectedCount = 0;
          foreach (var h in Host) if (h.IsChildChecked) SelectedCount++; else iFalse++;
          if (SelectedCount > 0 && iFalse == 0) this._IsParentChecked = true;
          if (SelectedCount == 0 && iFalse > 0) this._IsParentChecked = false;
          if (SelectedCount > 0 && iFalse > 0) this._IsParentChecked = null;
          OnPropertyChanged(nameof(IsParentChecked));
        }
      }
    
      public class HostName : BaseClass
      {
    
        private bool _isChildChecked = false;
        public bool IsChildChecked
        {
          get => this._isChildChecked;
          set
          {
            this._isChildChecked = value;
            OnPropertyChanged();
          }
        }
        public string Host { get; set; }
        public string HostType { get; set; }
      }
    
      public class BaseClass : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnPropertyChanged([CallerMemberName] string nameProp = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameProp));
      }
    }
    

0 additional answers

Sort by: Most helpful