WPF 中的奇怪绑定行为
我将尝试尽可能简洁地解释这一点。我有 2 个对象,第一个我们称为对象 A,它具有 Id 属性,第二个我们称为对象 B,它具有 ParentId 属性。明显的关系是对象 B 的 ParentId 设置为对象 A 的 Id 属性。我正在使用 MVVM 模式,因此在视图模型上我有 2 个 ObservableCollections,一个包含对象 A,另一个包含对象 B。在构建视图模型时,我创建并填充 ObservableCollection<'A'>名为 ListItems。我的 xaml 很简单,
<StackPanel>
<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ListItems}">
</ListBox>
<ComboBox SelectedValuePath="ParentId" SelectedValue="{Binding Path=ListItems/Id, Mode=OneWay}" ItemsSource="{Binding ComboItems}">
</ComboBox>
<Button Click="Button_Click" Content="Push Me"/>
</StackPanel>
正如您所看到的,组合框的 SelectedValue 绑定到 ListItems 当前项目的 Id 属性。所以本质上列表框和组合框都在主细节中。
如果按下按钮,它将填充 ObservableCollection<'B'>命名 ComboItems,它依次填充组合框。现在奇怪的事情就从这里开始了。当我启动程序时,如果我唯一做的就是按下按钮,然后在列表框中选择一个项目,则组合框将由于 SelectedValue 绑定而正确选择一个项目。但是,如果我启动程序并首先在列表框中选择一个项目,然后按下按钮,则当前组合框项目不会随当前列表框项目而改变。这种束缚似乎永远被打破了。有谁知道为什么会发生这种情况?
诗。如果我在设置 SelectedValue/SelectedValuePath 之前设置组合框上的 ItemsSource,则主/详细信息绑定将永远无法工作。我知道 xaml 有顺序,但这似乎有点脆弱。因此,如果有人对此也有意见,我会洗耳恭听。
谢谢,Nate
编辑-
绑定 SelectedValue 时,它非常脆弱。如果绑定有效,即没有在列表框中选择任何内容,然后填充组合框,如果您在组合框中选择一个项目,则绑定将中断。在浪费了很多时间之后,我选择绑定 SelectedItem。此绑定不会破坏我之前指定的任何条件。然而,我愿意回答为什么 SelectedValue 绑定如此荒谬。再次感谢所有已经回答或将要回答的人。
I will try and explain this as concise as possible. I have 2 objects, the first which we will call object A that has an Id property and the second we will call object B, which has a ParentId property. The obvious relationship is that object B's ParentId is set to an object A's Id property. I am using the MVVM pattern, so on the viewmodel I have 2 ObservableCollections, one containing objects A the other objects B. On construction of the viewmodel, I create and fill the ObservableCollection<'A'> named ListItems. My xaml is simple,
<StackPanel>
<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ListItems}">
</ListBox>
<ComboBox SelectedValuePath="ParentId" SelectedValue="{Binding Path=ListItems/Id, Mode=OneWay}" ItemsSource="{Binding ComboItems}">
</ComboBox>
<Button Click="Button_Click" Content="Push Me"/>
</StackPanel>
As you can see the combobox's SelectedValue is bound to the ListItems current item's Id property. So essentially the listbox and combobox are in a master details.
If you press the button, it will fill the ObservableCollection<'B'> name ComboItems, which in turn populates the combobox. Now here is where the oddity begins. When I start the program, if the only thing I do is press the button, and then afterwords select an item in the listbox, the combobox will properly select an item due to the SelectedValue binding. But if I start the program and first select an item in the listbox and then press the button, the current combobox item will not change with the current listbox item. The binding appears to be forever broken. Does anyone know why this happens?
Ps. If I set the ItemsSource on the combobox before I set the SelectedValue/SelectedValuePath, the master/detail binding will never work. I know there is order to xaml, but that seems a little fragile. So if anyone has input on that also, I am all ears.
Thanks, Nate
EDIT -
When binding SelectedValue, it is very fragile. If the binding is working, i.e. have not selected anything in the listbox and then filled the combobox, if you choose an item in the combobox, the binding will break. After much time wasted with this, I chose to bind SelectedItem. This binding does not break in any of the conditions I have previously specified. I would however take any answers as to why SelectedValue binding is so ridiculous. Thanks again to all that have answered or will answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是我们经常遇到的一个问题。
问题是,在
ItemsSource
属性获取新值后,SelectedValue
绑定将被清除。糟糕,直到今天我们还没有找到合适的解决方案。以下是一些解决方法:
设置新的 ItemsSource 后,立即重置代码中的
SelectedValue
绑定。您可以在转换器中执行此操作,或者在您知道哪个位置将替换 ItemsSource 绑定(例如DataContextChanged
事件)。不要在
ItemsSource
上使用Binding
,而是尝试使用CollectionViewSource
和 Filter。将所有项目放入CollectionViewSource
对象中,并在组合框更改值时过滤项目。当列表框引发
SelectionChanged
事件时,以旧方式手动获取项目。请注意,所有解决方案都不是书中最漂亮的。我会选择选项 2,在我看来这是最干净的;)
希望这会有所帮助!
Yeah this is a problem we stumble upon quite a lot.
The problem is that after the
ItemsSource
property gets a new value, theSelectedValue
binding will be cleared. Sucks, and until today we have not found a proper solution.Here are a few workarounds:
Reset the
SelectedValue
binding in code, as soon as the new ItemsSource has been set. You can do this in a converter, or somewhere you'll know which will replace the ItemsSource binding (like theDataContextChanged
event).Instead of using the
Binding
onItemsSource
, try using aCollectionViewSource
and a Filter. Put all your items in theCollectionViewSource
object and filter the items when your combobox changes value.Manually get your item the old fashion way when your listbox throws a
SelectionChanged
event.Mind you, all solutions are not the prettiest in the book. I would go for option 2, its the cleanest IMO ;)
Hope this helps!