这是我遇到的问题,我将使用我的演示中的类名来描述我的问题:
我必须在数据网格上显示某些内容,作为Item
的视图。但Item
本身是真实数据源的包装类Dummy
。
Container
是所有Dummy
的管理员,它会定期调用Poll
(在我的演示中,1s)并在内部查询远程服务器以确定当前值(在演示中,我只需翻转布尔值)。在此之后,Container
将遍历所有Item
和Notify
他们可能会进行更改。
但我的问题是,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();
}
}
}