ListBox - CollectionViewSource - 多线程 - 定时器 - 不更新

问题描述:

我有更新列表框的问题。
零件OD Window.xamlListBox - CollectionViewSource - 多线程 - 定时器 - 不更新

DataContext="{Binding Link, Source={StaticResource Computer}}"> 
<Window.Resources> 
     <CollectionViewSource Source="{Binding GetLinkInfo}" x:Key="compLink"> 
       <CollectionViewSource.SortDescriptions> 
         <scm:SortDescription PropertyName="Grupa" /> 
         <scm:SortDescription PropertyName="Host" /> 
       </CollectionViewSource.SortDescriptions> 
       <CollectionViewSource.GroupDescriptions> 
         <PropertyGroupDescription PropertyName="Grupa" /> 
       </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
</Window.Resources> 
<ListBox x:Name="_lbLink" ItemsSource="{Binding Source={StaticResource compLink}}"> 
</ListBox> 

而且Window.xaml.cs

ViewModel.cs

private void InitializedTimers() 
{ 
    _timer = new System.Timers.Timer(); 
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
    _timer.Interval = 10 * 1000; 
    _timer.Enabled = true; 
} 

private void OnTimedEvent(object source, ElapsedEventArgs e) 
{ 
    MainViewModelLocator mvm = Application.Current.Resources["Computer"] as MainViewModelLocator; 
    LinkViewModel lvm = mvm.Link; 
    if (lvm != null) 
    { 
     if ((from t in lvm.GetLinkInfo 
      where t.State == MRPLink.Link.StateLink.NOTCHECK 
      select t).Count() > 0) 
     { 
      int id = (from t in lvm.GetLinkInfo 
       where t.State == MRPLink.Link.StateLink.NOTCHECK 
       select t).First().ID; 
      lvm.UpdateStatus(id, MRPLink.Link.StateLink.CZECKOK, "xxxx"); 
     } 
    } 
} 

零件

public void UpdateStatus(int id, StateLink aState, string aIp) 
{ 
    _localinfo.Where(t => t.ID == id).ToList().ForEach(t => 
    { 
     t.State = aState; 
     if (!String.IsNullOrEmpty(aIp)) 
     { 
      t.LastIp = aIp; 
      t.LastSea = DateTime.Now; 
     } 
    }); 
    RaisePropertyChanged("GetLinkInfo"); 
} 

属性的调用,但没有更新列表框。
在我看来,这与计时器有关。但我不知道如何避开。

Thx寻求帮助。

ADDED
- I校正符号(选择吨).Count之间()> 0)从==
- 当我改变定时器DispatcherTimer我有存取权限DataContent,但不是全自动更新。

LinkViewModel lvm = this.DataContext as LinkViewModel; 

我可以使用_lbLink.Items.Refresh();任何变化:(之后

ADDED2
重播Stave B后,我想DispatcherHelper
我用它像
Unit testing with MVVM Light & DispatcherHelper

DispatcherHelper.CheckBeginInvokeOnUI(() => 
{ 
    lvm.UpdateStatus(id, MRPLink.Link.StateLink.CZECKOK, "xxx"); 
    //_lbLink.Items.Refresh(); 
}); 

但不会刷新窗台

ADDED3:
在此更改后,我看到执行属性GetLinkInfo但在ListBox中不刷新:(

ADDED4:

评论blindmeis我的应用程序正确刷新后。谢谢大家的帮助。

我看不到你的GetLinkInfo定义在哪里,所以我假设如下。

在你的窗口的datacontext中你有一个属性,你只需要初始化集合一次,只需添加,删除编辑项目,如果你需要。

public ObservableCollection<LinkInfo> GetLinkInfo 
{get; set;} 

在计时器线程或要更新您的状态,任何其他梅索德,所以只是做

Application.Current.Dispatcher.BeginInvoke(new Action(() =>lvm.UpdateStatus(id, MRPLink.Link.StateLink.CZECKOK, "xxxx");)); 

现在重要的东西,如果您添加或删除的项目到您的收藏中的ObservableCollection会提升INotifyPropertyChanged并更新您的用户界面。如果更新集合中的现有项目,则要更新的项目(类)应实现INotifyPropertyChanged。我不知道你的列表框正在显示什么,导致无法看到任何DataTemplate,但我认为你有一个。

+0

这是我仍然想念的,谢谢 – 2011-03-18 11:08:39

通过这个替换给updateStatus代码:

public void UpdateStatus(int id, StateLink aState, string aIp) 
{ 
    _localinfo.Where(t => t.ID == id).ToList().ForEach(t => 
    { 
     t.State = aState; 
     if (!String.IsNullOrEmpty(aIp)) 
     { 
      t.LastIp = aIp; 
      t.LastSea = DateTime.Now; 
     } 
    }); 
    Dispatcher.Invoke(()=>RaisePropertyChanged("GetLinkInfo")); 
} 

的UI相关的工作必须从UI线程调用。这是(很简单)分派器对象的目的。

+0

我在我的名字空间找不到Dispatcher.Invoke。 – 2011-03-18 10:37:04

+0

这取决于你的MVVM框架。例如,如果你使用MVVMLight工具包,你将不得不做''GalaSoft.MvvmLight.Threading.DispatcherHelper.UIDispatcher.Invoke(新操作(RaisePropertyChanged(“GetLinkInfo”));' – 2011-03-18 10:46:02

+0

我在尝试,但仍然有些问题。属性是执行但不具有约束力:( – 2011-03-18 10:54:28