简体   繁体   English

WPF - MVVM - C# 在 ItemsSource 更改后无法设置 combobox 的 SelectedItem

[英]WPF - MVVM - C# Cannot set SelectedItem of combobox after ItemsSource changes

I've been struggling with this problem for several days now.我已经为这个问题苦苦挣扎了好几天了。 I have a combobox that gets its ItemsSource twice.我有一个 combobox 两次获得它的 ItemsSource。 The first time i try to see if i have an offline backup of the data that i am trying to show.我第一次尝试查看是否有要显示的数据的脱机备份。 While the offline data is showing, the software needs to download the updated data from the database.在显示离线数据时,软件需要从数据库中下载更新的数据。

Everything works fine if i don't have any stored data in the offline backup.如果我在脱机备份中没有任何存储数据,一切正常。 The problem arises when i have a list of items backed up, i put it in the combobox itemsSource, and then change that list after a couple seconds.当我备份项目列表时出现问题,我将其放入 combobox 项目源,然后在几秒钟后更改该列表。

The list actually shows correctly, but the selectedItem (which is something that i get from the viewmodel) gets reset and i can't set it again from code-behind.该列表实际上显示正确,但是 selectedItem (这是我从视图模型中获得的)被重置,我无法从代码隐藏中再次设置它。 The SelectedItem property in the viewModel is actually properly set, but it doesn't get to the UI. viewModel 中的 SelectedItem 属性实际上已正确设置,但它并没有到达 UI。

The list is an ObservableCollection of the same type as the selectedItem.该列表是与 selectedItem 类型相同的 ObservableCollection。

My combobox我的 combobox

<ComboBox ItemsSource="{Binding SomeList, Mode=OneWay}"
                          SelectedItem="{Binding ListItem, Mode=TwoWay}"
                          DisplayMemberPath="ItemProperty"
                          Margin="10,0,0,0" Width="300" VerticalAlignment="Center"/>  

The way i set the selectedItem in both the offline and online methods:我在离线和在线方法中设置 selectedItem 的方式:

SomeList= await _mainRepository.BackEndOfflineFirst_GetList();

if (SomeList.Count > 0)
{ 
      ListItem = SomeList.SingleOrDefault(list=> list.Property.Equals(SomeVariable.Property));
}

Any help is appreciated.任何帮助表示赞赏。 I should mention that adding IsSynchronizedWithCurrentItem="True" to the combobox always makes the selectedItem the first item of the list.我应该提一下,将 IsSynchronizedWithCurrentItem="True" 添加到 combobox 始终使 selectedItem 成为列表的第一项。

The check for list.property equals another variable.property ALWAYS returns one single element that is guaranteed to be in the list, and is never null.对 list.property 的检查等于另一个变量。property 总是返回一个保证在列表中的元素,并且永远不会是 null。

Forgot to mention (kinda important, my bad), but i'm using Prism and i implement BindableBase, so the properties are defined as follows:忘了提(有点重要,我的错),但我使用的是 Prism 并且我实现了 BindableBase,所以属性定义如下:

private ObservableCollection<Type> _someList ;
    public ObservableCollection<Type> SomeList
    {
        get { return _someList ; }
        set { SetProperty(ref _someList , value); }
    }

It is impossible to infer the cause of the problem from your explanations.从您的解释中无法推断出问题的原因。 Everything is correct in the code examples - the problem is somewhere else.代码示例中的一切都是正确的 - 问题出在其他地方。 Just in case, I ask you to clarify: do you raise PropertyChanged in all properties?以防万一,我请您澄清一下:您是否在所有属性中提出 PropertyChanged?

One tip (including as a probable cause), use the ReadOnly property for the observable collection:一个提示(包括作为可能的原因),使用可观察集合的 ReadOnly 属性:

public ObservableCollection<...> SomeList {get;}
    = new ObservableCollection<...>();
SomeList.Clear();
foreach(var item in await _mainRepository.BackEndOfflineFirst_GetList())
    SomeList.Add(item);

Found out why it wasn't working.找出为什么它不起作用。

BindableBase propertyChanged only gets raised when the value actually changes. BindableBase propertyChanged 仅在值实际更改时才被引发。

I was getting basically the same object (different objects, same value), so it wasn't actually raising the propertyChanged.我得到了基本相同的 object(不同的对象,相同的值),所以它实际上并没有提高 propertyChanged。

To fix this, i put a为了解决这个问题,我放了一个

ListItem = null;
SomeList.Clear();

inside a finally clause, before actually giving the value i receive from the DB to the ListItem.在 finally 子句中,在实际将我从数据库收到的值提供给 ListItem 之前。

It also does not seem to work if i change properties too quickly (hence the finally clause), so i couldn't just put a如果我太快更改属性(因此是 finally 子句),它似乎也不起作用,所以我不能只放一个

SomeList.Clear();
SomeList = await...

back to back.背靠背。

Another problem i found was that SomeList.Clear() actually throws a NotSupportedException that wasn't actually showing up, hence skipping some of the code.我发现的另一个问题是 SomeList.Clear() 实际上抛出了一个 NotSupportedException 并没有真正出现,因此跳过了一些代码。

This was caused by SomeList being an ObservableCollection.这是由于 SomeList 是 ObservableCollection 造成的。 Changed it to a generic List and i can Clear it now.将其更改为通用列表,我现在可以清除它。 If you need to clear the ObservableCollection, a simple Collection = null;如果需要清除 ObservableCollection,简单的 Collection = null; works too.也可以。

Thank you to everyone that helped me.感谢所有帮助过我的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM