ListBox - CollectionViewSource - Multi Thread - Timers - Not Update
I have problems with update List Box.
Parts od Window.xamlDataContext="{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>
And Window.xaml.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");
}
}
}
Parts of ViewModel.cs
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");
}
Properties is called but the ListBox is not updated.
It seems to me that this is related the timer. But I do not know how to get around.Thx for help.
ADDED
- I co开发者_如何学JAVArrect sign (select t).Count() > 0) from == - When I change timer to DispatcherTimer I have acces to DataContent, but not update automaticly.LinkViewModel lvm = this.DataContext as LinkViewModel;
I can use _lbLink.Items.Refresh(); after any change :(
ADDED2
After replay Stave B I think about DispatcherHelper I use it like that Unit testing with MVVM Light & DispatcherHelperDispatcherHelper.CheckBeginInvokeOnUI(() =>
{
lvm.UpdateStatus(id, MRPLink.Link.StateLink.CZECKOK, "xxx");
//_lbLink.Items.Refresh();
});
But does not refresh sill.
ADDED3:
After this change I see execute properties GetLinkInfo but in ListBox not refresh :(ADDED4:
After comment blindmeis my application correct refresh. Thank all for help.
i can not see where your GetLinkInfo is defined so i assume the following.
in your datacontext of your window you have a property and you just init the collection once and just add, remove edit items if you need.
public ObservableCollection<LinkInfo> GetLinkInfo
{get; set;}
in your timer thread or any other methode you want to update your state, so just do it
Application.Current.Dispatcher.BeginInvoke(new Action(() =>lvm.UpdateStatus(id, MRPLink.Link.StateLink.CZECKOK, "xxxx");));
now the important stuff if you add or remove an item to your collection the observablecollection will raise INotifyPropertyChanged and your ui gets updated. if you update an existing item in your collection your item(class) to update should implement INotifyPropertyChanged. i wonder what your listbox is showing, cause a cant see any DataTemplate, but i think you have one.
Replace the UpdateStatus code by this one :
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"));
}
The UI related work must be called from the UI thread. This is (to be simple) the purpose of the Dispatcher object.
精彩评论