代码之家  ›  专栏  ›  技术社区  ›  Wallstreet Programmer

无法使用yield绑定到IEnumerable实现

  •  2
  • Wallstreet Programmer  · 技术社区  · 14 年前

    我有一个类封装了许多集合。我希望将此类绑定到列表框以显示集合中的项。类实现IEnumerable。当显示列表框时,我希望调用IEnumerable.GetEnumerator方法。但是,当getEnumerator方法使用yield关键字时,情况并非如此。但是,如果我从列表集合中返回枚举器,它将正常工作,那么每次显示窗口时都会调用getEnumerator方法。

    列表集合的枚举器有什么神奇之处???? 允许wpf itemscontrol获取快照(不需要更新)的正确接口是什么????我是要用的那个吗????

    下面的示例代码在每次打开新窗口时添加时间戳。但是,列表框从不显示多个时间戳,它是第一个(也是唯一一个)调用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>();
        }
    }
    
    1 回复  |  直到 14 年前
        1
  •  2
  •   Kris    14 年前

    当设置itemsource wpf时,通过 CollectionView 要启用排序,请对e.t.c.进行分组,这样在您的情况下,每个itemsControl都使用相同的枚举器,但不会重置它,因此只会显示最后一个项。

    如果需要快照行为,有几种方法,但为每个项创建一个新列表控件是最简单的。

    如果您希望所有这些文件都同步并自动更新,请参阅 ObservableCollection 实现 INotifyCollectionChanged .

    您可能也应该使用通用的IEnumerable接口。