This is a migrated thread and some comments may be shown as answers.

Silverlight MVVM IsChecked Not Firing for TwoWay Binding

1 Answer 67 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
David Kucharski
Top achievements
Rank 1
David Kucharski asked on 25 Jun 2012, 04:27 PM
I have a xaml with a radtree view on it.

<UserControl xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"  
    x:Class="Geomentum.MediaReach.Modules.AreaSelection.View.AreaSelectionView"
    xmlns:local="clr-namespace:Geomentum.MediaReach.Modules.AreaSelection.ViewModel"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
  
    <UserControl.Resources>
        <telerik:ContainerBindingCollection x:Name="BindingsCollection">
            <telerik:ContainerBinding PropertyName="IsChecked" Binding="{Binding Selected, Mode=TwoWay}" />
        </telerik:ContainerBindingCollection>
  
        <telerik:HierarchicalDataTemplate x:Key="DMATemplate" telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}">
            <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="10" FontFamily="Verdana" />
              
        </telerik:HierarchicalDataTemplate>
        <!--Data template for the State object-->
        <telerik:HierarchicalDataTemplate x:Key="StateTemplate"
               telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"
               ItemTemplate="{StaticResource DMATemplate}" ItemsSource="{Binding DMAs}">
            <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="10" FontFamily="Verdana" />
        </telerik:HierarchicalDataTemplate>
        <!--Data template for the Country object-->
        <telerik:HierarchicalDataTemplate x:Key="CountryTemplate"
             telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}"
             ItemTemplate="{StaticResource StateTemplate}" ItemsSource="{Binding States}">
            <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="10" FontFamily="Verdana" />
        </telerik:HierarchicalDataTemplate>
  
        <local:AreaSelectionSource x:Key="TreeViewDataSource"/>
  
        <Style x:Key="ItemContainerStyle" TargetType="telerik:RadTreeViewItem">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>
  
          
    </UserControl.Resources>
      
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <telerik:RadTreeView Grid.Row="0" ItemTemplate="{StaticResource CountryTemplate}" ItemContainerStyle="{StaticResource ItemContainerStyle}"
                ItemsSource="{Binding Source={StaticResource TreeViewDataSource}}" 
                             IsOptionElementsEnabled="True" ItemsOptionListType="CheckList" />
    </Grid>
</UserControl>

I am using the ContainerBindingCollection, HierarchicalDataTemplate, and a StaticResource as my datasource. I am binding it to my TreeViewDataSource that is in my ViewModel code below:

public class AreaSelectionSource : ObservableCollection<CountryModel>
{
    public AreaSelectionSource()
    {
        CountryModel c1 = new CountryModel()
        {
            Name = "USA1",
            ID = 1,
            Households = 100,
            Selected = true
        };
        StateModel s1 = new StateModel()
        {
            Name = "Illinois",
            ID = 2,
            Households = 200,
            Selected = false
        };
        StateModel s2 = new StateModel()
        {
            Name = "Indiana",
            ID = 3,
            Households = 200,
            Selected = true
        };
        c1.States.Add(s1);
        c1.States.Add(s2);
        s1.DMAs.Add(new DMAModel()
        {
            Name="Chicago",
            ID=1,
            Selected=true,
            Households = 200
        });
        s1.DMAs.Add(new DMAModel()
        {
            Name="Rockford",
            ID=2,
            Selected=false,
            Households = 200
        });
        this.Add(c1);
          
    }
}
This is an ObservableCollection of the CountryModel. Each CountryModel has a ObservableCollection of a StateModel along with an ID, Name, and Selected properties. Each StateModel has an ObservableCollection of a DMAModel along with an ID, Name, and Selected properties. Each DMAModel has an ID, Name, Selected properties.

DMAModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using System.Diagnostics;
  
namespace Geomentum.MediaReach.Infrastructure.Models
{
    public class DMAModel : INotifyPropertyChanged
    {
        private string _name;
        private int _id;
        private bool _selected;
        private int _households;
  
        public DMAModel()
        {
        }
  
        public string Name
        {
            get { return _name; }
            set { this._name = value; }
        }
        public int ID
        {
            get { return _id; }
            set { this._id = value; }
        }
        public bool Selected
        {
            get { return this._selected; }
            set
            {
  
                if (!value.Equals(_selected))
                {
                    _selected = value;
                    NotifyPropertyChanged("Selected");
                }
            }
        }
        public int Households
        {
            get { return _households; }
            set { this._households = value; }
        }
  
        #region INotifyPropertyChanged Members
  
        public event PropertyChangedEventHandler PropertyChanged;
  
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
  
        #endregion
  
    }
}

StateModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using System.Diagnostics;
  
namespace Geomentum.MediaReach.Infrastructure.Models
{
    public class StateModel : INotifyPropertyChanged
    {
        private string _name;
        private int _id;
        private bool _selected;
        private int _households;
        private ObservableCollection<DMAModel> _dmaList;
  
        public StateModel()
        {
            this._dmaList = new ObservableCollection<DMAModel>();
        }
  
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }
        public int ID
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public bool Selected
        {
            get { return this._selected; }
            set
            {
  
                if (!value.Equals(_selected))
                {
                    _selected = value;
                    NotifyPropertyChanged("Selected");
                }
            }
        }
        public int Households
        {
            get { return this._households; }
            set { this._households = value; }
        }
  
        public ObservableCollection<DMAModel> DMAs
        {
            get { return this._dmaList; }
            set { this._dmaList = value; }
        }
  
        #region INotifyPropertyChanged Members
  
        public event PropertyChangedEventHandler PropertyChanged;
  
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
  
        #endregion
    }
}

CountryModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using System.Diagnostics;
  
namespace Geomentum.MediaReach.Infrastructure.Models
{
    public class CountryModel : INotifyPropertyChanged
    {
        private string _name;
        private int _id;
        private bool _selected;
        private int _households;
        private ObservableCollection<StateModel> _stateList;
  
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }
        public int ID
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public bool Selected
        {
            get { return this._selected; }
            set 
            
  
                if (!value.Equals(_selected))
                {
                    _selected = value;
                    NotifyPropertyChanged("Selected");
                }
            }
        }
        public int Households
        {
            get { return this._households; }
            set { this._households = value; }
        }
  
        public ObservableCollection<StateModel> States
        {
            get { return this._stateList; }
            set { this._stateList = value; }
        }
  
        #region Constructors
        /// <summary>
        /// Class initializer.
        /// </summary>
        public CountryModel()
        {
            this._stateList = new ObservableCollection<StateModel>();
        }
  
        #endregion
  
  
        #region INotifyPropertyChanged Members
  
        public event PropertyChangedEventHandler PropertyChanged;
  
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
  
        #endregion
    }
}


I have also implemented the INotifyPropertyChanged on each of the Models.

Upon running my application, I do get a TreeView that has my information correctly displayed, checked and formatted. When I check/uncheck any of the boxes in my TreeView, I do not receive any NotifyPropertyChanged in my Country, State, or DMA models.

What I am missing or doing wrong?

1 Answer, 1 is accepted

Sort by
0
Petar Mladenov
Telerik team
answered on 28 Jun 2012, 04:20 PM
Hello David,

There are several known issues regarding the IsChecked and CheckState properties. However, In DataBinding scenarios it is mandatory to use CheckState instead of IsChecked. You can bind the CheckState to property of type ToggleState from your ViewModel directly, or to boolean? property and use Converter (to convert bool? to CheckState).
This may solve your scenario, but I guess you will also need the TriState functionality of the RadTreeView. If you need it you will have to define the tri-state logic in your ViewModels due to a known limitation. Setting the IsIntriStateMode property to true works correctly only in static scenarios. When it comes up to databinding, we highly suggest you to follow the approach described in this code library project.

Regards,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Tags
TreeView
Asked by
David Kucharski
Top achievements
Rank 1
Answers by
Petar Mladenov
Telerik team
Share this question
or