为什么PropertyChanged在绑定时可能为null?

时间:2014-11-14 16:10:30

标签: c# wpf

这是我遇到的问题,我将使用我的演示中的类名来描述我的问题:

我必须在数据网格上显示某些内容,作为Item的视图。但Item本身是真实数据源的包装类Dummy

Container是所有Dummy的管理员,它会定期调用Poll(在我的演示中,1s)并在内部查询远程服务器以确定当前值(在演示中,我只需翻转布尔值)。在此之后,Container将遍历所有ItemNotify他们可能会进行更改。

但我的问题是,Notify调用的Container中的if分支无法进入,因为PropertyChanged为空!但如果我在DataGrid中更改它,即dg,则双击,此事件会被订阅。所以我的问题是,我如何成功通知Container?有没有办法让DataGrid始终订阅PropertyChanged

顺便说一句,如果我使用调试器进入,它们也是空的。

以下是我的演示代码:

XAML:

<Window x:Class="WpfApplication6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="dg"  Margin="0,0,0,35"/>
        <Button Content="Button" Margin="0,0,10,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75" Click="Button_Click"/>

    </Grid>
</Window>

c#part:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WpfApplication6
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Container _container;
        public MainWindow()
        {
            InitializeComponent();
            _container = new Container();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            dg.ItemsSource = _container.GetItems();
        }
    }

    public class Dummy
    {
        public Dummy()
        {
            _done=false;
        }
        private bool _done;
        public bool Done {
            get { return _done; }
            // set will trigger something remotely too.
            set { _done = value; }
        }

        public void Poll() { _done=!_done;}
    }

    public class Item : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private Dummy dummy;
        public Item(Dummy dum)
        {
            dummy = dum;
        }
        public bool Done
        {
            get { return dummy.Done; }
            set
            {
                dummy.Done = value;
                Notify();
            }
        }

        public void Notify()
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs("Done"));
        }
    }

    public class Container
    {
        private List<Dummy> dummies;
        private DispatcherTimer _updateTimer;
        public Container()
        {
            dummies = (from i in Enumerable.Range(0, 10)
                       select new Dummy()).ToList();
        }

        private IEnumerable<Item> items;
        public Item[] GetItems()
        {
            if (_updateTimer != null)
                _updateTimer.Stop();
            items=dummies.Select(x => new Item(x));
            _updateTimer = new DispatcherTimer();
            _updateTimer.Interval = TimeSpan.FromSeconds(1);
            _updateTimer.Tick += (_1, _2) =>
            {
                foreach (var item in dummies)
                {
                    item.Poll();
                }
                foreach (var item in items)
                {
                    item.Notify();
                }
            };
            _updateTimer.Start();
            return items.ToArray();
        }
    }
}

0 个答案:

没有答案