我有一个数据绑定UI。当我更改基础数据时,UI更新正常,但控件似乎仍然订阅了我的PropertyChanged事件。
我有以下内容:
绑定到ListA的ItemsControl
每个项目ListA包含一个子列表 使用其他显示的ListB ItemsControl的
使用a显示每个项目ListB TextBox绑定到字符串属性 通过INotifyPropertyChanged
这是XAML:
<UserControl x:Class="SilverlightBindingTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<DataTemplate x:Key="DataTempl" >
<TextBox Text="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate x:Key="PageTempl" >
<ItemsControl ItemsSource="{Binding Datas}" ItemTemplate="{StaticResource DataTempl}"></ItemsControl>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<ItemsControl ItemsSource="{Binding Pages}" ItemTemplate="{StaticResource PageTempl}"></ItemsControl>
<Button Content="Swap list" Click="ButtonClick1"></Button>
<Button Content="Change base data" Click="ButtonClick2"></Button>
</StackPanel>
</Grid>
</UserControl>
以下是代码:
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Collections.Generic;
namespace SilverlightBindingTest
{
public partial class MainPage : INotifyPropertyChanged
{
private List<DataGroupClass> pages1 = new List<DataGroupClass>();
private List<DataGroupClass> pages2 = new List<DataGroupClass>();
public MainPage()
{
InitializeComponent();
List<DataClass> group = new List<DataClass>();
group.Add(new DataClass("value 1"));
group.Add(new DataClass("value 2"));
group.Add(new DataClass("value 3"));
pages1.Add(new DataGroupClass(group));
group = new List<DataClass>();
group.Add(new DataClass("value 4"));
group.Add(new DataClass("value 5"));
group.Add(new DataClass("value 6"));
pages2.Add(new DataGroupClass(group));
DataContext = this;
}
private List<DataGroupClass> pages = new List<DataGroupClass>();
public List<DataGroupClass> Pages
{
get { return pages; }
set
{
pages = value;
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs("Pages"));
}
}
}
private void ButtonClick1(object sender, RoutedEventArgs e)
{
Debug.WriteLine("-------------------\n");
if (Pages == pages1)
{
Pages = pages2;
}
else
{
Pages = pages1;
}
}
private bool toggle;
private void ButtonClick2(object sender, RoutedEventArgs e)
{
if (toggle)
{
pages1[0].Datas[0].Value = "tim";
pages2[0].Datas[0].Value = "lajos";
}
else
{
pages1[0].Datas[0].Value = "joe";
pages2[0].Datas[0].Value = "james";
}
toggle = !toggle;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class DataClass : INotifyPropertyChanged
{
private string value;
public string Value
{
get
{
Debug.WriteLine("Get Value:" + value);
return value;
}
set
{
Debug.WriteLine("Set Value: " + this.value + " => " + value);
this.value = value;
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs("Value"));
}
}
}
public DataClass(string value)
{
Value = value;
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class DataGroupClass
{
private List<DataClass> datas;
public List<DataClass> Datas
{
get
{
Debug.WriteLine("Get Datas");
return datas;
}
set
{
Debug.WriteLine("Set Datas");
datas = value;
}
}
public DataGroupClass(List<DataClass> datas)
{
Datas = datas;
}
}
}
以下是跟踪输出:
点击“交换列表”十次(看起来都很好):
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
-------------------
Get Datas
Get Value:value 4
Get Value:value 5
Get Value:value 6
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
-------------------
Get Datas
Get Value:value 4
Get Value:value 5
Get Value:value 6
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
-------------------
Get Datas
Get Value:value 4
Get Value:value 5
Get Value:value 6
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
-------------------
Get Datas
Get Value:value 4
Get Value:value 5
Get Value:value 6
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
-------------------
Get Datas
Get Value:value 4
Get Value:value 5
Get Value:value 6
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
点击“更改基础数据”(查看多次调用获取价值):
-------------------
Get Datas
Get Value:value 1
Get Value:value 2
Get Value:value 3
Get Datas
Set Value: value 1 => joe
Get Value:joe
Get Value:joe
Get Value:joe
Get Value:joe
Get Value:joe
Get Value:joe
Get Datas
Set Value: value 4 => james
Get Value:james
Get Value:james
Get Value:james
Get Value:james
Get Value:james
我认为我错过了什么,但是什么?
任何帮助都非常感谢!
答案 0 :(得分:2)
不,你没有错过任何东西。在您按“更改基础数据”时,仍有一些UI元素仍然被垃圾收集器收集。 UI元素仍然保留其绑定表达式,而后者又保留了属性更改事件。
最终将收集那些未使用的UI元素,并且将停止收听属性更改事件。
您可以通过将GC.Collect()
放在button1点击代码的末尾来证明这一点(尽管我当然不建议您执行此实际代码)。通过强制收集,您将看到您永远不会读取Value
属性的多个。