question

abijithgowda-5277 avatar image
0 Votes"
abijithgowda-5277 asked ·

WPF label not updating value on the UI

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-wpf
· 2
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, in every HostName item you use a separate instance of ViewModel. In Window you use an another instance of VM. SelectedDevicesCounter executes in separate instance and the window remains unchanged.

 <Window x:Class="Window016"
 ...
    <Window.Resources>
       <local:ViewModel x:Key="vm"/>
     <Style x:Key="HighlightingTextStyle" TargetType="Label">
 ...
    <Grid DataContext="{StaticResource vm}">
 ...
     
  public class VM : BaseViewModel
  {
 ...
     
  public class HostName : BaseViewModel
     {
         VM ncmvm = new VM();
 …
                 ncmvm.SelectedDevicesCounter(Constants.counter); <---------------------------------
0 Votes 0 ·

Hi Peter,
I understand the UI is not being updated since a new instance of the VM is being created every time. Is there any way to implement this as i need to get the count of the selected devices.
If so, can you please let me know as to how this can be achieved.

0 Votes 0 ·

1 Answer

PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

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



· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

That did the trick!! Simply WOW!!

Thank you Peter!!

0 Votes 0 ·