【问题标题】:WPF Silverlight Datagrid in real time, refresh? Timer?WPF Silverlight Datagrid 实时,刷新?计时器?
【发布时间】:2012-10-06 19:44:30
【问题描述】:

我有一定的数据网格,我需要“刷新”每……让我们说 1 分钟。

计时器是最好的选择吗?

    public PageMain()
    {
        InitializeComponent();
        DataGridFill();
        InitTimer();
    }

    private void InitTimer()
    {
        disTimer = new Timer(new TimeSpan(0, 1, 0).TotalMilliseconds);
        disTimer.Elapsed += disTimer_Elapsed;
        disTimer.Start();
    }

    void disTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        DataGridFill();
    }

    private void DataGridFill()
    {
        var items = GetItems(1);
        ICollectionView itemsView =
            CollectionViewSource.GetDefaultView(items);

        itemsView.GroupDescriptions.Add(new PropertyGroupDescription("MyCustomGroup"));
        // Set the view as the DataContext for the DataGrid
        AmbientesDataGrid.DataContext = itemsView;
    }

有没有更“脏”的解决方案?

【问题讨论】:

  • “刷新”是什么意思?您希望网格中的数据每 1 分钟更新一次吗?
  • 是的,正是……在这里,让我编辑和改写
  • “刷新”DataGrid 的最佳方式是将其绑定到项目集合,并每 X 分钟更新项目的源集合。这样您就不必引用 DataGrid 本身,因此您的 UI 逻辑和应用程序逻辑保持分离,如果您的刷新需要一段时间,您可以在后台线程上运行它而不会锁定您的 UI。
  • 问题是因为这是一个定时器,它开始一个额外的线程。因此更改上下文或 ItemSource 会引发 InvalidOperationException ...我现在正在研究 BackgroundWorker。我想这可能会有所帮助。
  • @apacay 使用TimerDispatcherTimer。您不能直接从另一个线程更新集合,但您可以将数据放入另一个线程的临时集合中,然后在主线程上更新绑定集合中的数据。

标签: c# wpf refresh wpfdatagrid silverlight-5.0


【解决方案1】:

“刷新”DataGrid 的最佳方法是将其绑定到项目集合,并每 X 分钟更新一次项目的源集合。

<DataGrid ItemsSource="{Binding MyCollection}" ... />

这样,您永远不必引用 DataGrid 本身,因此您的 UI 逻辑和应用程序逻辑保持分离,如果您的刷新需要一段时间,您可以在后台线程上运行它而不会锁定您的 UI。

由于 WPF 无法从另一个线程更新在一个线程上创建的对象,您可能希望获取数据并将其存储在后台线程上的临时集合中,然后在主 UI 线程上更新绑定的集合。

对于计时位,如果需要,请使用TimerDispatcherTimer

var timer = new System.Windows.Threading.DispatcherTimer();
timer.Tick += Timer_Tick;
timer.Interval = new TimeSpan(0,1,0);
timer.Start();


private void Timer_Tick(object sender, EventArgs e)
{
    MyCollection = GetUpdatedCollectionData();
}

【讨论】:

  • 值得指出的是,你需要一个支持INotifyPropertyChanged的集合,比如ObservableCollection
  • @weston 不完全准确 INotifyPropertyChanged 将适用于集合中的项目,如果它们发生变化,它还需要实现 INotifyCollectionChanged 以满足从集合本身添加/删除的项目。不过,您建议 ObservableCollection&lt;T&gt; 是正确的。
  • @TrevorPilley 好点。想一想,如果你像 Rachel 一样改变整个列表,你可以使用任何东西。 IE。如果属性 MyCollection 触发通知,则它可以是任何 IEnumerable。但我更喜欢有一个只读的 IEnumerable 属性,后面有一个 ObservableCollection。
  • 是的,如果您替换网格绑定到的整个列表,数据绑定将引发数据源更改事件(或任何 WPF 等效事件),这将导致整个网格无论如何都要刷新。
  • 通常,一旦您创建了 ItemsSource,最好更新已更改行中的数据,而不是更改整个 DataSource。否则,您将丢失所选行的上下文。您还必须处理重绘的 UI 惩罚(即使它很微妙)。
【解决方案2】:

我喜欢的方法:

public sealed class ViewModel
{
    /// <summary>
    /// As this is readonly, the list property cannot change, just it's content so
    /// I don't need to send notify messages.
    /// </summary>
    private readonly ObservableCollection<T> _list = new ObservableCollection<T>();

    /// <summary>
    /// Bind to me.
    /// I publish as IEnumerable<T>, no need to show your inner workings.
    /// </summary>
    public IEnumerable<T> List { get { return _list; } }

    /// <summary>
    /// Add items. Call from a despatch timer if you wish.
    /// </summary>
    /// <param name="newItems"></param>
    public void AddItems(IEnumerable<T> newItems)
    {            
        foreach(var item in newItems)
        {
            _list.Add(item);
        }
    }

    /// <summary>
    /// Sets the list of items. Call from a despatch timer if you wish.
    /// </summary>
    /// <param name="newItems"></param>
    public void SetItems(IEnumerable<T> newItems)
    {
        _list.Clear();
        AddItems(newItems);
    }
}

不喜欢在ObservableCollection&lt;T&gt; 中缺少像样的AddRange/ReplaceRange?我也不是,但这里是ObservableCollection&lt;T&gt; 的后代,添加了一个消息效率高的AddRange,以及单元测试:

ObservableCollection Doesn't support AddRange method, so I get notified for each item added, besides what about INotifyCollectionChanging?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 2011-09-21
    • 2012-12-09
    • 2013-11-06
    • 2010-12-19
    相关资源
    最近更新 更多