【发布时间】:2010-08-18 19:23:45
【问题描述】:
我有一个封装了一堆集合的类。我想将此类绑定到列表框以显示集合中的项目。该类实现 IEnumerable。当显示列表框时,我期望调用 IEnumerable.GetEnumerator 方法。然而,当 GetEnumerator 方法使用 yield 关键字时,情况并非如此。但是,如果我要从 List 集合返回枚举器,它会正常工作,每次显示窗口时都会调用 GetEnumerator 方法。
List 集合的枚举器有什么神奇之处??? 允许 WPF 项目控件获取快照的正确接口是什么(不需要更新)??? IList 是要使用的吗???
以下示例代码会在每次打开新窗口时添加一个时间戳。但是,列表框永远不会显示多个时间戳,这是第一次(也是唯一一次)调用 GetEnumerator 的时间戳数。计数增加,因此添加了时间戳。更改 GetEnumerator 方法以返回列表集合的枚举器将导致每次打开新窗口时都会调用 GetEnumerator 方法。
XAML:
<Window x:Class="YieldTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<StackPanel>
<Button Content="Open" Click="Button_Click" />
<TextBlock Text="{Binding Path=Count}" />
<ListBox ItemsSource="{Binding}" />
</StackPanel>
</Window>
后面的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
namespace YieldTest
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Window1 window1 = new Window1();
window1.DataContext = _timeStamps;
_timeStamps.Add(DateTime.Now);
window1.Show();
}
private static TimeStamps _timeStamps = new TimeStamps();
}
public class TimeStamps : IEnumerable
{
public void Add(DateTime time1)
{
_timeStamps.Add(time1);
}
public int Count { get { return _timeStamps.Count; } }
public IEnumerator GetEnumerator()
{
Debug.WriteLine("GetEnumerator");
// Returning the enumerator of _timeStamps will result in
// GetEnumerator called every time a new window is opened,
// which is the expected result
// return _timeStamps.GetEnumerator();
// Using yield will result in GetEnumerator is called only
// one time for the first window opened. This means that
// newer windows will have stale data.
foreach (DateTime timeStamp in _timeStamps)
{
yield return timeStamp;
}
}
private List<DateTime> _timeStamps = new List<DateTime>();
}
}
【问题讨论】:
-
我发现对我来说获得可绑定数据源的两个解决方案是实现 IList 和 IEnumerator,或者实现 IEnumerable 和 INotifyCollectionChanged。我决定让数据源实现 IEnumerable 和 INotifyCollectionChanged,因为它的实现较少,并且客户端代码无法添加项目。
标签: wpf data-binding ienumerable yield