在更改绑定到TreeView时获得奇怪的行为

时间:2013-09-24 16:27:05

标签: wpf silverlight binding treeview radio-button

我有ObservableCollection Fathers,其中包含属性ObservableCollection Sons。 我正在TreeView设置其DataContext属性中显示它。 Sons属性显示为每个父亲下的ListBox单选按钮 - 绑定到ItemsSource

首次将树视图的DataContext设置为父亲列表,一切正常。根据数据检查单选按钮。

现在,我将TreeView.DataContext设置为null - 因此数据将消失。然后回到我第一次设置的原始Fathers ObservableCollection。

现在由于某种原因,单选按钮停止与son对象同步。 而且我变得更深了,我看到儿子对象中的setter(绑定到单选按钮)由于某种原因而被假提升。我猜猜与绑定有关的事情。

绑定后是否存在TreeView或ObservableCollection正在保存的缓存?我想让它像我第一次设置绑定一样工作 - 这就像它应该只调用getter一样。

感谢。

这是我的树视图

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

背后的对象

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

在我的应用程序中,我添加了这个treeview控件并将其命名为m_objSimpleTree。 此代码是初始化

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;

当我按下按钮时,我正在做这个

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

此代码将已将IsChecked的子设置器提升为false(为什么???) 但RadioButton仍将被检查。 第二次按下按钮。这将是未经检查的,并且安装者没有加注。 当我按下单选按钮时它会提高两倍的安装人员。第一次假 第二个是真的。

无法理解为什么会发生这种情况..我能想到的唯一想法是树视图在第一个绑定中保存了某些内容或类似的内容。

1 个答案:

答案 0 :(得分:0)

这样做是因为你已经使用了两个绑定来控制

binding code project

当您在视图上更改某些thig时,在双向绑定中,数据也会保存在对象中。 datacontext被分配到哪个。尝试oneWay为此。但需要小心,好像你想用两种方式保存数据一种方式可能没有用。 MVVM建议使用双向绑定来保存数据,但是你需要刷新列表然后创建一个新对象:)

同时尝试清除Binding

Clear binding

我不确定从未尝试过的最后一个链接。请通过它可能会有一个想法。但是,由于您可能需要再次使用新对象,因此可以创建一个新对象以分配给datacontext。

--- 编辑 -----

这是一个xaml代码

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

和c#

using System;

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

命名空间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;
        }
    }
}

}

现在主要的一点是,如果你想为单个单选按钮实现它,那么你需要实现Click事件并将单选按钮设置为false,下次设置为true :)否则你需要使用checkbox一旦检查过一个单选按钮就无法转换为假