我有一个Activity
对象,其中包含许多属性。其中之一如下:
public ActivityStatus Status
{
get { return status; }
set { status = value; NotifyPropertyChanged("Status"); }
}
ActivityStatus
类只有两个属性:
public Guid Guid
{
get { return guid; }
set { guid = value; NotifyPropertyChanged("Guid"); }
}
public string Name
{
get { return name; }
set { name = value; NotifyPropertyChanged("Name"); }
}
和 Equals
方法:
public override bool Equals(object otherObject)
{
if (!(otherObject is ActivityStatus)) return false;
return Equals(otherObject as ActivityStatus);
}
public bool Equals(ActivityStatus otherStatus)
{
if (!(otherStatus is ActivityStatus) || otherStatus == null) return false;
return Guid == otherStatus.Guid && Name == otherStatus.Name;
}
我有一个ActivityViewModel
类作为ActivityView
类的DataContext
。 ActivityViewModel
有一个类型为Activity
的Activity
属性和一个类型为ObservableCollection<ActivityStatus>
的ActivityStatuses
属性,还有其他属性。在ActivityView
中,我声明了一个ComboBox
如下:
<ComboBox ItemsSource="{Binding ActivityStatuses}"
SelectedItem="{Binding Activity.Status, Mode=TwoWay}"
DisplayMemberPath="Name" />
这使我能够从ComboBox中选择ActivityStatus,这会正确更新viewmodel中Activity属性的Status属性。问题在于双向绑定...当加载新的Activity时,ComboBox.SelectedItem不会更新以显示Activity.Status属性值。使用此ComboBox声明,SelectedItem绑定到Activity中的ActivityStatus对象,而这个对象与ViewModel中ActivityStatuses属性中具有相同值的对象不同。因此,WPF框架认为这些项不同,并且不会选择ComboBox中的项。
如果我在每次加载Activity后将具有相同值的集合项分配给Activity.Status属性,则ComboBox会在其ItemsSource集合中找到匹配项并正确设置SelectedItem属性来显示该值。然而,我不想这样做,因为Activity类中还有许多类似的属性,我必须在任何想要双向绑定到ComboBox的地方重复此代码。
因此,我还尝试了以下方式绑定到ActivityStatus.Guid属性:
<ComboBox ItemsSource="{Binding ActivityStatuses}"
SelectedValue="{Binding Activity.Status.Guid, Mode=TwoWay}"
SelectedValuePath="Guid"
DisplayMemberPath="Name" />
当加载不同的Activity对象时,此代码正确地从ComboBox.ItemsSource集合中选择具有与Activity.Status属性中Guid相同的对象。使用此方法的问题在于SelectedValue绑定到ActivityStatus对象中的ActivityStatus.Guid属性,因此在UI中更改值时,只有ActivityStatus对象的'Guid'属性会更新,而名称保持不变。 Activity.Status属性中的对象除其Guid属性的值外不会改变。我也尝试了实现Equals方法,因为我认为ComboBox会使用它来比较对象,但是没有任何区别。因此,最后我很困惑,并渴望找到一个简单干净的方法来解决这个问题...希望ComboBox上有一个简单的属性,我可能错过了。
我只是想能够在ComboBox中选择项目并使Activity.Status对象相应地更改,并从代码中更改Activity.Status属性的值,并相应地更新ComboBox.SelectedItem。我会感激任何建议。
更新>>> 阅读了Will的回复后,我在新解决方案中尝试了他的代码示例,并看到它按预期工作。然后,我彻底检查了他的代码,并发现它与我的代码相同,因此再次运行了我的解决方案(自发布以来第一次)。令我完全惊讶的是,它按预期工作,而我没有改变任何代码!
这让我非常困惑,我花了一些时间来找出发生了什么。事实证明,问题是/是Visual Studio 2010!我已将Equals方法添加到我的数据类型中作为最后一个阶段。由于某种原因,Visual Studio在运行应用程序时没有构建数据类型项目。
因此,应用程序必须使用旧的dll文件,并且我的更改未被使用...我曾经想知道为什么我的断点在Equals方法上从未被触发过。这导致我认为实现Equals方法没有帮助。Visual Studio今天具有相同的行为,这就是我找出发生了什么的方式。
我检查了解决方案中的项目构建顺序,但那里正确地列出了数据类型项目的位置。但是,在运行应用程序时,Visual Studio的输出窗口显示项目dll以不同的顺序加载。我不确定为什么运行应用程序不再进行完整的构建,但至少我知道在运行应用程序之前必须先构建该项目中的更改。
最后的更新>>> 我刚刚发现我的数据类型项目为什么没有构建...我查看了Configuration Manager窗口,并发现该项目的平台不正确,并且Build复选框变为未选中状态!我不知道这是如何发生的,但很高兴终于找到了问题的根源。