Silverlight MVVM IsChecked Not Firing for TwoWay Binding

2 posts, 0 answers
  1. David Kucharski
    David Kucharski avatar
    50 posts
    Member since:
    Feb 2010

    Posted 25 Jun 2012 Link to this post

    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?

  2. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 28 Jun 2012 Link to this post

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

  3. DevCraft banner
Back to Top