У меня есть класс, инкапсулирующий кучу коллекций.Я хотел бы связать этот класс со списком для отображения элементов в коллекциях.Класс реализует 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>();
}
}