当前位置:网站首页>To solve the problem that the data interface is not updated after WPF binding set

To solve the problem that the data interface is not updated after WPF binding set

2020-11-06 21:30:04 Irving the procedural ape

solve WPF After binding the set, the data change interface does not update

solve  WPF  After binding the set, the data change interface does not update

Independent observers 2020 year 9 month 9 Japan

 

stay .NET Core 3.1 Of  WPF  The program is intended to use  ListBox  Binding displays a collection ( Just meet the demand , It doesn't matter what kind of set ), Here are Xaml Code ( Just a glance , It's not the point of this article ):

<ListBox ItemsSource="{Binding SipRegistrations, Mode=OneWay}" SelectedValue="{Binding SelectedAccountBinding, Mode=OneWayToSource}"> <ListBox.ItemTemplate>  <DataTemplate>   <TextBlock Text="{Binding SIPAccount.SIPUsername}"></TextBlock>  </DataTemplate> </ListBox.ItemTemplate></ListBox>

 

ViewModel There's a set of targets in , The present is a  List.

There are two ways to implement property change notification , First, use.  PropertyChanged.Fody, Second, use custom binding base class  BindableBase, Here's the picture .

 

The following is mainly about data changes ( Collection adds content ) after , There is no problem of updating the front desk interface . To be specific ,List.Add after , The first time it worked , But then it doesn't work , The interface always displays only one piece of data .

 

original ( No effect ):

SipRegistrations.RemoveAll(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername); //  Remove duplicates ( If any )SipRegistrations.Add(binding); //  Add a new item 

 

Guess because List There is no change in the citation of , So it's thought that the attribute hasn't changed , And then there is no change notice .

In fact, this situation requires notice of change , The recommended use is  ObservableCollection:

 

But I used it before  ObservableCollection  No success , Instead, use List Yes. , So let's take a look at it first List How to solve it .

 

Variant one ( Debugging has a chance to have an effect ):

// Add contacts to the collection and handle interface binding ;SipRegistrations.RemoveAll(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername);List<SIPAccountBinding> tempList = SipRegistrations; // Temporary assembly ;SipRegistrations = new List<SIPAccountBinding>();  // The target set is set to empty first ;tempList.Add(binding);         // Temporary collection adds new items ;SipRegistrations = tempList;       // The temporary set is assigned to the target set ;

 

Variant one uses temporary variables as a transit , Force the target set ( References to ) Change , But the result is that only in debugging with a very small probability of success .

Because this part of the code is in asynchronous logic , So it could be in a multithreaded environment , and List Not thread safe , So there's variant 2 of the lock version .

 

Variant two ( No effect , It should be similar to variant 1 ):

#region  member /// <summary>///  Lock object /// </summary>private object _lockObj = new object();#endregion// Lock ;lock (_lockObj){ // Add contacts to the collection and handle interface binding ; SipRegistrations.RemoveAll(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername); List<SIPAccountBinding> tempList = SipRegistrations; SipRegistrations = new List<SIPAccountBinding>(); tempList.Add(binding); SipRegistrations = tempList;}

 

It doesn't work with a lock ( But locks are needed ), I think of , Since there is a chance of success when debugging , So is it related to the speed of code running ? So a thread sleep is added between the target set's null and its reassignment , You can really , This is the following Variant 3 .

 

Variant three ( Effective ):

lock (_lockOb.........

版权声明
本文为[Irving the procedural ape]所创,转载请带上原文链接,感谢