WPF组合框绑定:无法更改选择

3
在这个问题上浪费了几小时,紧跟着我上一个问题的脚步 (上一个问题链接),我开始觉得Framework 4是微妙邪恶的大师,或者我的电脑被鬼附身了。
我在一个WPF表单上有三个组合框和一个文本框,并且我拥有一个开箱即用的Subsonic 3 ActiveRecord DAL。 当我加载此“编辑记录”表单时,组合框会正确填充,它们选择正确的项目,并且文本框具有正确的文本。我可以更改TextBox文本并成功保存记录,但是组合框无法更改。列表会下拉并突出显示,但是单击项目后,所选项目保持不变。
这是我的XAML:
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Asset</TextBlock>
    <ComboBox Name="cboAsset" Width="180"  
      DisplayMemberPath="AssetName"
      SelectedValuePath="AssetID" 
      SelectedValue="{Binding AssetID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Status</TextBlock>
    <ComboBox Name="cboStatus" Width="180" 
      DisplayMemberPath="JobStatusDesc"  SelectedValuePath="JobStatusID"  
      SelectedValue="{Binding JobStatusID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Category</TextBlock>
    <ComboBox Name="cboCategories" Width="180" 
      DisplayMemberPath="CategoryName"
      SelectedValuePath="JobCategoryID"
      SelectedValue="{Binding JobCategoryID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Reason</TextBlock>
    <TextBox Name="txtReason" Width="380" Text="{Binding Reason}"/>
</StackPanel>

以下是我代码的相关片段(intJobID作为参数传入):

SvcMgrDAL.Job oJob;
IQueryable<SvcMgrDAL.JobCategory> oCategories = SvcMgrDAL.JobCategory.All().OrderBy(x => x.CategoryName);
IQueryable<SvcMgrDAL.Asset> oAssets = SvcMgrDAL.Asset.All().OrderBy(x => x.AssetName);
IQueryable<SvcMgrDAL.JobStatus> oStatus = SvcMgrDAL.JobStatus.All();

    cboCategories.ItemsSource = oCategories;
    cboStatus.ItemsSource = oStatus;
    cboAsset.ItemsSource = oAssets;
    this.JobID = intJobID;
    oJob = SvcMgrDAL.Job.SingleOrDefault(x => x.JobID == intJobID);
    this.DataContext = oJob;

我尝试过以下方法:

  • 明确设置IsReadOnly="false"IsSynchronizedWithCurrentItem="True"
  • 将下拉框ItemSourcesIQueryables更改为Lists
  • 构建自己的Job对象(使用INotifyPropertyChanged的普通实体类)
  • 尝试了所有下拉框的绑定模式
  • ItemsSource="{Binding}"

Subsonic DAL没有实现INotifyPropertyChanged,但我认为它不需要像这样简单的绑定那样。我只想能够从下拉列表中选择一些内容并保存。

与我的上一个问题进行比较(链接在此消息顶部),我似乎遇到了一些关于数据源的奇怪问题。也许这是Subsonic的问题?

编辑:由于某种原因,仅在AssetID属性上第一次点击时才会触发set访问器。WPF现在变成了WTF :)

编辑2:你开玩笑吧-我已经删除了绑定(即它只有一个displaymemberpath、一个valuememberpath和一个itemssouce),它仍然会出现这种问题!它接受你的第一个选择,然后就不会改变了。


你尝试在 Job.AssetID的 set 访问器中设置断点了吗?它被触发了吗?当你单步执行时会发生什么?它实际上有改变吗?也许它会抛出一个异常? - Fyodor Soikin
如果我使用Subsonic数据访问层,它不会触发访问器。如果我使用自己的对象,也不会触发它,但是在组合框周围会出现红色矩形...?? - SteveCav
请检查一下 - 红色的异常方框是我自己对象中的类型错误 (Int16 vs 32)。所以,访问器并没有被调用。 - SteveCav
查看我回答的编辑,获取有关发现绑定问题的信息。 - Drew Noakes
6个回答

4

如果使用object.Equals()方法比较新选择的项目和当前选择的项目,如果它们被认为是相等的,则WPF组合框不会更改所选项目(即newlyslected.Equals(previoslySelected))。

在绑定组合框项目的类上覆盖Equals方法,应该解决您看到的问题。


1

我已经将问题缩小到使用作为ComboBoxItems的Subsonic对象上。 如果您创建一个新类,其代码与Subsonic相关部分完全相同,则可以正常工作。 如果您在组合框中使用POCOs/datatables,并在编辑记录时使用Subsonic,则可以正常工作。 但是,如果您同时使用Subsonic,则无法正常工作。

我原本希望扩展Subsonic对象,而不必编写完整的BLL层。看来我只能面临要么这样做,要么放弃Subsonic作为DAL。我可能会为Subsonic社区提出一个更具体的问题。

衷心感谢所有做出贡献的人。


1

虽然这个话题比较老,但我也遇到了同样的问题,而且很难找到解决方案。以下内容可能会对其他人有所帮助。

问题出在WPF不能检测用户选择的不同项(症状是-事件ComboBox_SelectionChanged只在第一次选择时触发)。我的情况是,查找下拉列表从DISTINCT查询构建的IList中进行,使用NHibernate ICriteria.SetResultTransformer的结果仅返回某些字段,重要的是不包括唯一实体ID。

解决方案是在检索后遍历IList,并为每个实体分配一个唯一的ID。WPF将它们视为单独的实体并适当地处理。

这只是一个值查找 - 我需要的是值内容。

这些“临时”实体永远不会被持久化。在这种情况下,这比因GUI问题而覆盖对象的Equals方法更好。另一种替代方法是将列表复制或转换为WPF使用值字段确定“差异”的格式...


0

很难从你的代码小样本中确定,但是尝试注释掉这行代码:

//this.DataContext = oJob; 

看看这是否有帮助。

设置DataContext和ItemsSource可能会导致冲突。


即使两个都被移除了,它仍然在执行! - SteveCav

0

听起来好像该字段是只读的,或者您的更改没有被持久化。绑定设置新值后,它会重新读取属性以确保它实际上已更改。如果您的属性返回旧值,则它将在组合框中重新选择,从而看起来值从未更改。

我不知道那个DAL,但您能否逐步执行属性setter代码?您还可能遇到类型转换问题。

编辑阅读您关于红色矩形的评论——听起来好像您的属性(或与绑定相关的某些内容)正在引发异常。除非您在UI中使用数据验证。您可以在调试器的设置中打开“所有异常中断”,假设您正在使用Visual Studio。

编辑2您应该检查VS输出窗格是否有与绑定相关的任何错误消息。您还可以阅读this blog post,其中提供了有关调试绑定的更多信息。


异常与此无关,已经解决。我设置了“在所有异常处中断”并检查了输出,但没有发现任何问题。 - SteveCav
我尝试使用博客文章中的转换器技术。它没有触发“返回值行”,而是抛出了“此方法不应该被调用”的异常(仅适用于Asset组合框)。此时的值是AssetID的初始值,而不是新选择的值。我不知道接下来该怎么办。 - SteveCav
使用追踪级别时,Asset组合框返回的是现有值而不是所选值。其他组合框则根本没有任何追踪反应。 - SteveCav

0

你是否为你的组合框编写了任何全局样式,可能存在错误或缺失?或者你是使用纯默认样式来设置你的组合框?尝试移除任何应用的默认样式。

你是否连接了任何事件?如果你的代码连接了像PreviewMouseLeftButtonUp这样的事件,并将事件标记为已处理,则可能会导致组合框忽略并不会选择任何内容。


不,这就是令人困惑的地方。没有样式,甚至没有任何事件。我刚刚下载了SS,生成了DAL,创建了一个表单,添加了一些组合框,但它不起作用! - SteveCav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接