0

I have ObservableCollection Fathers which contains property ObservableCollection Sons. And I'm displaying it on the TreeView setting its DataContext property. The Sons property displays as a ListBox of radio button under each Father - binded to ItemsSource.

First time setting the DataContext of the tree view to the fathers list, everything is working good. The radio buttons are checked according to the data.

Now, I'm setting the TreeView.DataContext to null - so the data will disappear. and then back to the original Fathers ObservableCollection which I set in the first time.

And now from some reason the radio buttons stopped being synchronized with the son object. And I got deeper and I saw that the setter in the son object (that binded to the radio button) is raised with false from some reason. I Guess something related to the binding.

Is there any cache that the TreeView, or the ObservableCollection is saving after binding ? I want it to work like the first time I set the bind - Which there like it should only the getter is being called like it should.

Thanks.

This is my Tree view

    <UserControl x:Class="Tester.CTLMyTree"
    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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Border Background="#FF919191" BorderThickness="1" CornerRadius="5"
                        HorizontalAlignment="Left"  VerticalAlignment="Top"
                        Padding="5" BorderBrush="Black" Height="207" Width="190">
            <Border.Resources>
                <sdk:HierarchicalDataTemplate x:Key="LayerListTemplate">
                    <StackPanel Orientation="Vertical"  Width="200" >
                        <TextBlock Text="Hello"/>

                        <ListBox x:Name="lstViews" ItemsSource="{Binding Sons}" BorderThickness="0" Width="200">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <RadioButton Content="Check" IsChecked="{Binding IsChecked, Mode=TwoWay}"/>                                    
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>

                    </StackPanel>
                </sdk:HierarchicalDataTemplate>
            </Border.Resources>

            <sdk:TreeView ItemsSource="{Binding}" ItemTemplate="{StaticResource LayerListTemplate}" x:Name="myTreeView" />
        </Border>
    </Grid>
</UserControl>

The Objects behind

public class CCFather
    {
        public CCFather()
        {
            Sons = new ObservableCollection<CCSon>();
        }

        public ObservableCollection<CCSon> Sons
        {
            get;
            set;
        }
    }

    public class CCSon
    {
        private bool m_blnChecked;

        public bool IsChecked
        {
            get
            {
                return m_blnChecked;
            }
            set
            {
                m_blnChecked = value;
            }
        }
    }

In my application i added this treeview control and called it m_objSimpleTree. This code is the initializing

m_objItems = new ObservableCollection<CCFather>();
CCFather objItem1 = new CCFather();
objItem1.Sons.Add(new CCSon());
objItem1.Sons[0].IsChecked = true;

m_objItems.Add(objItem1);

m_objSimpleTree.myTreeView.DataContext = m_objItems;

And when i press a button i'm doing this

m_objSimpleTree.myTreeView.DataContext = null;
m_objSimpleTree.myTreeView.DataContext = m_objItems;

This code will raise already the IsChecked setter of the son to false (Why ???) But the RadioButton will still be checked. Second time pressing the button. it will be unchecked and the setter didn't raise. When i'm pressing on the radio button It's raising twice the setter. First time with false second with true.

Can't figure why it's happening.. The only think i can think of is that the treeview is saving something in the first binding or something like this.

Raziza O
  • 1,560
  • 1
  • 17
  • 37
  • Thought maybe the binding of the listbox inside need to be nulled as well. So i got it from the TreeViewItem, and resetting its ItemsSource before resetting the DataContext of the treeView.. But no luck :(.. Someone ? – Raziza O Sep 24 '13 at 17:16
  • Posting your code would really help simplify your question – Omri Btian Sep 24 '13 at 17:17

1 Answers1

0

It does so because you have used twoWay binding for the control

binding code project

In a two way binding when you change some thig on the view then the data gets saved in the object also . to which the datacontext is assigned. try oneWay for that . But need to be careful as if you wanna save data using twoWay one way might not help. MVVM suggests to use two way binding to save data but you want a refreshed list then create a new object :)

Also try clear Binding

Clear binding

Am not sure of the last link as never tried. Please o through it might get an idea. But since you might need a new object again so you can create a fresh object to assign to datacontext.

--- EDIT-----

Here's a xaml code

<UserControl
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SilverlightSOApp.MainPage"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
    <Border Background="#FF919191" BorderThickness="1" CornerRadius="5"
                    HorizontalAlignment="Left"  VerticalAlignment="Top"
                    Padding="5" BorderBrush="Black" Height="207" Width="190">
        <Border.Resources>
            <sdk:HierarchicalDataTemplate x:Key="LayerListTemplate">
                <StackPanel Orientation="Vertical"  Width="200" >
                    <TextBlock Text="Hello"/>

                    <ListBox x:Name="lstViews" ItemsSource="{Binding Sons}" BorderThickness="0" Width="200">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <RadioButton Content="Check"  GroupName="abcd" IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
                                    <RadioButton Content="Check" GroupName="abcd" IsChecked="{Binding IsChecked2, Mode=TwoWay}"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

                </StackPanel>
            </sdk:HierarchicalDataTemplate>
        </Border.Resources>

        <sdk:TreeView ItemsSource="{Binding}" ItemTemplate="{StaticResource LayerListTemplate}" x:Name="myTreeView" />
    </Border>
    <Button Content="Button" HorizontalAlignment="Left" Margin="303,268,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>

</Grid>

And the c#

using System;

using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Net; using System.Windows; using System.Windows.Browser; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes;

namespace SilverlightSOApp { public partial class MainPage : UserControl {

    private ObservableCollection<CCFather> m_objItems;

    public MainPage()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(MainPage_Loaded);
    }
    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        m_objItems = new ObservableCollection<CCFather>();
        CCFather objItem1 = new CCFather();
        objItem1.Sons.Add(new CCSon());
        objItem1.Sons[0].IsChecked = false;

        m_objItems.Add(objItem1);

        myTreeView.DataContext = m_objItems;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        myTreeView.DataContext = null;
        myTreeView.DataContext = m_objItems;
    }

}

public class CCFather
{
    public CCFather()
    {
        Sons = new ObservableCollection<CCSon>();
    }

    public ObservableCollection<CCSon> Sons
    {
        get;
        set;
    }
}

public class CCSon
{
    private bool m_blnChecked;
    private bool m_blnChecked2;

    public bool IsChecked
    {
        get
        {
            return m_blnChecked;
        }
        set
        {
            m_blnChecked = value;
        }
    }
    public bool IsChecked2
    {
        get
        {
            return m_blnChecked2;
        }
        set
        {
            m_blnChecked2 = value;
        }
    }
}

}

Now the main point if you want to implement it for single radio button then you need to implement the Click event and set radio button to false and next time to true :) or else you need to use a checkbox one radio button once checked cannot be converted to false

Community
  • 1
  • 1
Anobik
  • 4,841
  • 2
  • 17
  • 32
  • I need it to be twoWay binding. The thing is that on the first biding like it should, the TreeView is only getting data from the object. on the second and on, its setting.. about the second link u sent, i will try it out and let you know. Thank for replying – Raziza O Sep 26 '13 at 15:56
  • Try creatinf a new object else the old data will persist :) – Anobik Sep 26 '13 at 17:38
  • Tried the ClearBinding solution, Nope.. It is not working. Someone ? – Raziza O Sep 29 '13 at 04:51
  • I hope if you create a new object then the data doesnot remain same?? – Anobik Sep 29 '13 at 04:54
  • add a break point here `m_objSimpleTree.myTreeView.DataContext = null; m_objSimpleTree.myTreeView.DataContext = m_objItems;` and see the object already contains the prev check box value since it is a two way binding. In case you need to set data for another field say once u posted one data for one person then for next then you will need a new object for them :) – Anobik Sep 29 '13 at 04:59
  • I'm sorry i didn't get your answer. I tried also not to changed the binding, but only the items in the list. I've removed the item and add it again to the list. i'm not touching the the DataContext and it's still activating the set accessor. – Raziza O Sep 29 '13 at 05:14
  • Creating new object in the list is working but i don't want to duplicate all my objects every time something is changing in the list – Raziza O Sep 29 '13 at 05:20
  • Wait i am checking in device :) – Anobik Sep 29 '13 at 05:20
  • Tried to add another IsChecked property on the CCFather object. and bind it. but this one is working properly. So it means that it's related to the list box or the radio buttons inside – Raziza O Sep 29 '13 at 05:33
  • Please check it . and you might also need a check box if one radio button is what you want to implement. :) – Anobik Sep 29 '13 at 05:42
  • OK. First of all - YEAHH!!!!! and now :) From your example i've found out that **i did not assign the GroupName for the RadioButton**, and this is solving all the problems in the world !!! at least in my app. Thanks very much my friend. – Raziza O Sep 29 '13 at 05:53