为什么我的 ComboBox SelectedItem 为空?

发布于 2024-12-02 16:16:08 字数 2179 浏览 1 评论 0 原文

我有一个 WPF/MVVM(使用 MVVM-Light)应用程序设置,其中包含一个位于 DataTemplate 内的 ComboBox。 ComboBox 的 XAML 如下所示:

<ComboBox x:Name="cbTeachers" 
          Grid.Column="1" 
          Style="{StaticResource ComboBox}" 
          ItemsSource="{Binding Teachers}" 
          Grid.Row="3" 
          DisplayMemberPath="Name" 
          SelectedValuePath="Id" 
          IsSynchronizedWithCurrentItem="False" 
          SelectedItem="{Binding Path=SelectedTeacher}">
     <i:Interaction.Triggers>
          <i:EventTrigger EventName="SelectionChanged">
               <i:InvokeCommandAction Command="{Binding TeacherSelectedCommand}"
                                      CommandParameter="{Binding SelectedItem, ElementName=cbTeachers}" />
          </i:EventTrigger>
     </i:Interaction.Triggers>
</ComboBox>

ItemsSource 的 Teachers 属性是一种名为 ObservableRangeCollection 的类型,基于此处找到的代码:http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx,但它与标准 ObservableCollection 非常相似。当设置另一个属性时,会设置 SelectedTeacher 属性,并且代码看起来与此非常相似:

this.SelectedTeacher = (from t in this.Teachers where t.Id == this.DataItem.Teacher.Id select t).Single();

我遇到的问题(对我来说毫无意义)是,一旦我设置,SelectedTeacher 就会重置为 null它。我可以单步执行调试器并看到 SelectedTeacher 有一个值,当我在该属性的 setter 上放置断点时,它肯定有该值。但随后该属性再次被空值击中。我检查了调用堆栈,它显示唯一的前一行是外部代码(这是有道理的,因为我只在一个地方设置该属性,并且如预期的那样,它只被命中一次)。展开调用堆栈窗口中的“外部代码”选项会显示典型的 WPF 调用堆栈,其中可能有 40 个方法,因此它绝对是 WPF 内部的,而不是我要重置它的操作。事实上,当我删除 SelectedItem="{Binding SelectedTeacher}" 时,该属性的设置器不会被再次调用(因此它保留其值),但 ComboBox 当然也不会显示所选项目。我尝试在我的视图模型中实现 SelectedIndex 选项,但这也不起作用。 ComboBox 只是不会选择该项目。我可以很好地更改组合框中选定的项目,但初始设置不起作用。

有什么想法吗?根据我搜索到的所有内容,它可能与我使用 DataTemplate 有关,但我必须这样做,因为该模板是父 ContentTemplateSelector 实现的一部分。

附带说明一下,我有多个属性绑定到此 DataTemplate 中的控件,这是唯一一个不起作用的属性。其他的工作完美。我还尝试过带有和不带有“IsSynchronizedWithCurrentItem”标志的 ComboBox,但没有什么区别。

I have a WPF/MVVM (using MVVM-Light) app setup with a ComboBox that is inside a DataTemplate. The XAML of the ComboBox looks like this:

<ComboBox x:Name="cbTeachers" 
          Grid.Column="1" 
          Style="{StaticResource ComboBox}" 
          ItemsSource="{Binding Teachers}" 
          Grid.Row="3" 
          DisplayMemberPath="Name" 
          SelectedValuePath="Id" 
          IsSynchronizedWithCurrentItem="False" 
          SelectedItem="{Binding Path=SelectedTeacher}">
     <i:Interaction.Triggers>
          <i:EventTrigger EventName="SelectionChanged">
               <i:InvokeCommandAction Command="{Binding TeacherSelectedCommand}"
                                      CommandParameter="{Binding SelectedItem, ElementName=cbTeachers}" />
          </i:EventTrigger>
     </i:Interaction.Triggers>
</ComboBox>

The Teachers property for the ItemsSource is a type called ObservableRangeCollection and is based on the code found here: http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx, but it's very similar to a standard ObservableCollection. The SelectedTeacher property is set when another property is set and the code looks very similiar to this:

this.SelectedTeacher = (from t in this.Teachers where t.Id == this.DataItem.Teacher.Id select t).Single();

The problem I am running into, which makes zero sense to me, is SelectedTeacher is getting reset to null once I set it. I can step through the debugger and see SelectedTeacher has a value and when I put a breakpoint on the setter for the property it definitely has the value. But then that property gets hit again with a null value. I checked the call stack and it showed the only preceeding line as being External Code (which makes sense since I only set that property in one place and it only gets hit once, as expected). Expanding the External Code option in the call stack window shows the typical WPF call stack of maybe 40 methods so it's definitely internal to WPF and not something I am doing to make it reset. In fact, when I remove the SelectedItem="{Binding SelectedTeacher}" the setter for that property doesn't get called a second time (thus it retains its value), but of course the ComboBox doesn't show the selected item either. I tried implementing a SelectedIndex option in my viewmodel but that didn't work either. The ComboBox just won't select the item. I can change the selected item in the ComboBox just fine, but the initial setting won't take.

Any ideas? Based on everything I've searched it might be related to me using a DataTemplate, but I have to because that template is part of a parent ContentTemplateSelector implementation.

As a side note, I have multiple properties that bind to controls in this DataTemplate and this is the only one that doesn't work. The others work perfectly. I have also tried the ComboBox with and without the "IsSynchronizedWithCurrentItem" flag and it made no difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浸婚纱 2024-12-09 16:16:08

您是否尝试过删除 EventTrigger 内容并仅

SelectedItem="{Binding Path=SelectedTeacher, Mode=TwoWay}"

与 Mode=TwoWay 一起使用?

我不清楚您想通过 EventTrigger 实现什么目的?

have you tried to remove to EventTrigger stuff and just to use

SelectedItem="{Binding Path=SelectedTeacher, Mode=TwoWay}"

with Mode=TwoWay?

its not clear to me what you want to achieve with your EventTrigger?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文