开发者

ListBox - CollectionViewSource - Multi Thread - Timers - Not Update

开发者 https://www.devze.com 2023-02-17 19:53 出处:网络
I have problems with update List Box. Parts od Window.xaml DataContext=\"{Binding Link, Source={StaticResource Computer}}\">

I have problems with update List Box.

Parts od Window.xaml

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>

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 & DispatcherHelper

DispatcherHelper.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.

0

精彩评论

暂无评论...
验证码 换一张
取 消