WPF - MVVM - C# 无法在 ItemsSource 更改后设置组合框的 SelectedItem
WPF - MVVM - C# Cannot set SelectedItem of combobox after ItemsSource changes
几天来我一直在为这个问题苦苦挣扎。
我有一个组合框,它两次获取 ItemsSource。
我第一次尝试查看是否有我要显示的数据的离线备份。
显示离线数据时,软件需要从数据库下载更新后的数据。
如果我在离线备份中没有任何存储的数据,一切正常。
当我备份了一个项目列表时,问题就出现了,我把它放在组合框 itemsSource 中,然后在几秒钟后更改该列表。
列表实际上显示正确,但 selectedItem(这是我从视图模型中获得的东西)被重置,我无法从代码隐藏中再次设置它。
viewModel中的SelectedItem 属性其实是设置正确的,但是没有到达UI.
该列表是与 selectedItem 类型相同的 ObservableCollection。
我的组合框
<ComboBox ItemsSource="{Binding SomeList, Mode=OneWay}"
SelectedItem="{Binding ListItem, Mode=TwoWay}"
DisplayMemberPath="ItemProperty"
Margin="10,0,0,0" Width="300" VerticalAlignment="Center"/>
我在离线和在线方法中设置 selectedItem 的方式:
SomeList= await _mainRepository.BackEndOfflineFirst_GetList();
if (SomeList.Count > 0)
{
ListItem = SomeList.SingleOrDefault(list=> list.Property.Equals(SomeVariable.Property));
}
感谢任何帮助。
我应该提到,将 IsSynchronizedWithCurrentItem="True" 添加到组合框总是使 selectedItem 成为列表的第一项。
list.property 的检查等于另一个 variable.property 总是 returns 保证在列表中的单个元素,并且永远不会为空。
忘了提(有点重要,我的错),但我正在使用 Prism 并且我实现了 BindableBase,所以属性定义如下:
private ObservableCollection<Type> _someList ;
public ObservableCollection<Type> SomeList
{
get { return _someList ; }
set { SetProperty(ref _someList , value); }
}
从您的解释中无法推断出问题的原因。
代码示例中的一切都是正确的 - 问题出在其他地方。
为了以防万一,我请你澄清一下:你是否在所有属性中引发 PropertyChanged?
一个提示(包括作为可能原因),对可观察集合使用 ReadOnly 属性:
public ObservableCollection<...> SomeList {get;}
= new ObservableCollection<...>();
SomeList.Clear();
foreach(var item in await _mainRepository.BackEndOfflineFirst_GetList())
SomeList.Add(item);
找出为什么它不起作用。
BindableBase propertyChanged 仅在值实际更改时引发。
我得到的是基本相同的对象(不同的对象,相同的值),所以它实际上并没有提高 propertyChanged。
为了解决这个问题,我放了一个
ListItem = null;
SomeList.Clear();
在 finally 子句中,在实际将从数据库接收到的值提供给 ListItem 之前。
如果我太快地更改属性(因此有 finally 子句),它似乎也不起作用,所以我不能只放一个
SomeList.Clear();
SomeList = await...
背靠背。
我发现的另一个问题是 SomeList.Clear() 实际上抛出了一个 NotSupportedException,它实际上并没有出现,因此跳过了一些代码。
这是因为 SomeList 是一个 ObservableCollection。将其更改为通用列表,我现在可以清除它。
如果您需要清除 ObservableCollection,一个简单的 Collection = null;也有效。
感谢所有帮助过我的人。
几天来我一直在为这个问题苦苦挣扎。 我有一个组合框,它两次获取 ItemsSource。 我第一次尝试查看是否有我要显示的数据的离线备份。 显示离线数据时,软件需要从数据库下载更新后的数据。
如果我在离线备份中没有任何存储的数据,一切正常。 当我备份了一个项目列表时,问题就出现了,我把它放在组合框 itemsSource 中,然后在几秒钟后更改该列表。
列表实际上显示正确,但 selectedItem(这是我从视图模型中获得的东西)被重置,我无法从代码隐藏中再次设置它。 viewModel中的SelectedItem 属性其实是设置正确的,但是没有到达UI.
该列表是与 selectedItem 类型相同的 ObservableCollection。
我的组合框
<ComboBox ItemsSource="{Binding SomeList, Mode=OneWay}"
SelectedItem="{Binding ListItem, Mode=TwoWay}"
DisplayMemberPath="ItemProperty"
Margin="10,0,0,0" Width="300" VerticalAlignment="Center"/>
我在离线和在线方法中设置 selectedItem 的方式:
SomeList= await _mainRepository.BackEndOfflineFirst_GetList();
if (SomeList.Count > 0)
{
ListItem = SomeList.SingleOrDefault(list=> list.Property.Equals(SomeVariable.Property));
}
感谢任何帮助。 我应该提到,将 IsSynchronizedWithCurrentItem="True" 添加到组合框总是使 selectedItem 成为列表的第一项。
list.property 的检查等于另一个 variable.property 总是 returns 保证在列表中的单个元素,并且永远不会为空。
忘了提(有点重要,我的错),但我正在使用 Prism 并且我实现了 BindableBase,所以属性定义如下:
private ObservableCollection<Type> _someList ;
public ObservableCollection<Type> SomeList
{
get { return _someList ; }
set { SetProperty(ref _someList , value); }
}
从您的解释中无法推断出问题的原因。 代码示例中的一切都是正确的 - 问题出在其他地方。 为了以防万一,我请你澄清一下:你是否在所有属性中引发 PropertyChanged?
一个提示(包括作为可能原因),对可观察集合使用 ReadOnly 属性:
public ObservableCollection<...> SomeList {get;}
= new ObservableCollection<...>();
SomeList.Clear();
foreach(var item in await _mainRepository.BackEndOfflineFirst_GetList())
SomeList.Add(item);
找出为什么它不起作用。
BindableBase propertyChanged 仅在值实际更改时引发。
我得到的是基本相同的对象(不同的对象,相同的值),所以它实际上并没有提高 propertyChanged。
为了解决这个问题,我放了一个
ListItem = null;
SomeList.Clear();
在 finally 子句中,在实际将从数据库接收到的值提供给 ListItem 之前。
如果我太快地更改属性(因此有 finally 子句),它似乎也不起作用,所以我不能只放一个
SomeList.Clear();
SomeList = await...
背靠背。
我发现的另一个问题是 SomeList.Clear() 实际上抛出了一个 NotSupportedException,它实际上并没有出现,因此跳过了一些代码。
这是因为 SomeList 是一个 ObservableCollection。将其更改为通用列表,我现在可以清除它。 如果您需要清除 ObservableCollection,一个简单的 Collection = null;也有效。
感谢所有帮助过我的人。