【发布时间】:2015-03-14 18:36:30
【问题描述】:
我正在尝试让我的双向绑定工作。
这些 ComboBox 应该将它们自己(TwoWay)绑定到它们在 VM 中的属性:
<ComboBox x:Name="_cmbCatT1" Margin="5,1,5,10"
ItemsSource="{Binding MVM.CategoryLinkCollection}"
DisplayMemberPath="Category.Name"
SelectedValue="{Binding MVM.SelectedTier1, Mode=TwoWay}"
SelectedValuePath="Category"/>
<ComboBox x:Name="_cmbCatT2" Margin="5,1,5,10"
DataContext="{Binding SelectedItem, ElementName=_cmbCatT1}"
ItemsSource="{Binding CategoryLinkCollection}"
DisplayMemberPath="Category.Name"
SelectedValue="{Binding MVM.SelectedTier2, ElementName=_vManipulation, Mode=TwoWay}"
SelectedValuePath="Category"/>
<ComboBox x:Name="_cmbCatT3" Margin="5,1,5,10"
DataContext="{Binding SelectedItem, ElementName=_cmbCatT2}"
ItemsSource="{Binding CategoryLinkCollection}"
DisplayMemberPath="Category.Name"
SelectedValue="{Binding MVM.SelectedTier3, ElementName=_vManipulation, Mode=TwoWay}"
SelectedValuePath="Category"/>
虚拟机:
private string selectedName;
public string SelectedName {
get {
return this.selectedName;
}
set {
this.selectedName = value;
OnPropertyChanged("SelectedName");
}
}
private string selectedDescription;
public string SelectedDescription {
get {
return this.selectedDescription;
}
set {
this.selectedDescription = value;
OnPropertyChanged("SelectedDescription");
}
}
private string selectedRemark;
public string SelectedRemark {
get {
return this.selectedRemark;
}
set {
this.selectedRemark = value;
OnPropertyChanged("SelectedRemark");
}
}
private string selectedValue;
public string SelectedValue {
get {
return this.selectedValue;
}
set {
this.selectedValue = value;
OnPropertyChanged("SelectedValue");
}
}
private Model.Room selectedRoom;
public Model.Room SelectedRoom {
get {
return this.selectedRoom;
}
set {
this.selectedRoom = value;
OnPropertyChanged("SelectedRoom");
}
}
private Model.Locker selectedLocker;
public Model.Locker SelectedLocker {
get {
return this.selectedLocker;
}
set {
this.selectedLocker = value;
OnPropertyChanged("SelectedLocker");
}
}
private Model.Category selectedTier1;
public Model.Category SelectedTier1 {
get {
return this.selectedTier1;
}
set {
this.selectedTier1 = value;
OnPropertyChanged("SelectedTier1");
}
}
private Model.Category selectedTier2;
public Model.Category SelectedTier2 {
get {
return this.selectedTier2;
}
set {
this.selectedTier2 = value;
OnPropertyChanged("SelectedTier2");
}
}
private Model.Category selectedTier3;
public Model.Category SelectedTier3 {
get {
return this.selectedTier3;
}
set {
this.selectedTier3 = value;
OnPropertyChanged("SelectedTier3");
}
}
private Model.Manufacturer selectedManufacturer;
public Model.Manufacturer SelectedManufacturer {
get {
return this.selectedManufacturer;
}
set {
this.selectedManufacturer = value;
OnPropertyChanged("SelectedManufacturer");
}
}
请注意,ItemsSource 的 DataType 是“CategoryLinkCollection”,其中包含“Category”-Property 和“CategoryLinkCollection”的 Obs.Collection。通过 SelectedValuePath 将“类别”“保存”在 VM 的属性中。
只要我在 ComboBox 中选择一个项目,一切都可以正常工作,但是 当我手动设置 VM-Properties 时,ComboBoxes 不会从包含已定义类别的 ItemsSource 中预先选择项目。正常的字符串值只适用于 finde(文本框)
我认为由于类型不同(ComboBox = CategoryLinkCollection with ValuePath to Category,Property = Category),我认为它永远不会起作用,但也许你们中的一些人可能会证明我错了。如果您需要更多信息,请告诉我。
更新 1:
我只记得主要原因应该在其他地方,因为模型“制造商”没有包装器 - 所以 ItemsSource 包含与属性相同数据类型的集合。
XAML:
<ComboBox x:Name="_cmbManufacturer"
ItemsSource="{Binding MVM.ManufacturerCollection}"
DisplayMemberPath="Name"
SelectedItem="{Binding MVM.SelectedManufacturer, Mode=TwoWay}"/>
虚拟机: 见上文。
更新 2:
首先,请远离那些糟糕的类别并前往更新 1 中提到的制造商,因为这是同样的问题,但更容易进入。
我现在手动设置后检查了 SelectedManufacturer-Property,以防在设置时出现问题。 SelectedManufacturer-Property 包含制造商(非空),但 UI 仍未更新。
更新 3:
使用诊断 NS 后,我从输出窗口中得到以下输出:
System.Windows.Data 警告:60:BindingExpression (hash=43478430):默认模式解析为 TwoWay
System.Windows.Data 警告:61:BindingExpression (hash=43478430):默认更新触发器解析为 PropertyChanged
System.Windows.Data 警告:62:BindingExpression (hash=43478430):附加到 System.Windows.Controls.ComboBox.SelectedItem (hash=10372298)
System.Windows.Data 警告:67:BindingExpression (hash=43478430):解析源
System.Windows.Data 警告:70:BindingExpression (hash=43478430):找到数据上下文元素:ComboBox (hash=10372298) (OK)
System.Windows.Data 警告:78:BindingExpression (hash=43478430):使用根项操作激活 (hash=64100268)
System.Windows.Data 警告:107:BindingExpression (hash=43478430):在级别 0 使用缓存访问器进行 Manipulation.MVM:RuntimePropertyInfo(MVM)
System.Windows.Data 警告:104:BindingExpression (hash=43478430):使用访问器 RuntimePropertyInfo(MVM) 将级别 0 的项目替换为 Manipulation (hash=64100268)
System.Windows.Data 警告:101 : BindingExpression (hash=43478430): GetValue at level 0 from Manipulation (hash=64100268) using RuntimePropertyInfo(MVM): ManipulationViewModel (hash=11088040)
System.Windows.Data 警告:108:BindingExpression (hash=43478430):在级别 1 - 对于 ManipulationViewModel.SelectedManufacturer 找到访问器 RuntimePropertyInfo(SelectedManufacturer)
System.Windows.Data 警告:104:BindingExpression (hash=43478430):使用访问器 RuntimePropertyInfo(SelectedManufacturer) 将级别 1 的项目替换为 ManipulationViewModel (hash=11088040)
System.Windows.Data 警告:101 : BindingExpression (hash=43478430): GetValue at level 1 from ManipulationViewModel (hash=11088040) using RuntimePropertyInfo(SelectedManufacturer): Manufacturer (hash=14500136)
System.Windows.Data 警告:80 : BindingExpression (hash=43478430): TransferValue - 获得原始值制造商 (hash=14500136)
System.Windows.Data 警告:84 : BindingExpression (hash=43478430): TransferValue - 隐式转换器产生的制造商 (hash=14500136)
System.Windows.Data 警告:89:BindingExpression (hash=43478430): TransferValue - 使用最终值制造商 (hash=14500136)
更新 4:
制造商类:
public class Manufacturer : Base.SqlBase {
public Manufacturer(int id, string name) {
this.SqlID = id;
this.Name = name;
}
}
SqlBase 类:
public abstract class SqlBase : INotifyPropertyChanged {
public int SqlID { get; set; }
private string _name;
public string Name {
get {
return _name;
}
protected set {
this._name = value;
PropertyChangedHandler("Name");
}
}
public void SetId(int id) {
this.SqlID = id;
PropertyChangedHandler("SqlID");
}
private void PropertyChangedHandler(string propertyName) {
PropertyChangedEventHandler temp = PropertyChanged;
if (temp != null) {
temp(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
实体类:
public class Entity : Base.SqlBase {
public string Description { get; private set; }
public string Remark { get; private set; }
public int Value { get; private set; }
public Model.CategoryWrapper Categories { get; private set; }
public Model.Manufacturer Manufacturer { get; private set; }
public Model.Locker Locker { get; private set; }
public Entity(string name, string desc, string remark, int value, Model.CategoryWrapper cat, Model.Manufacturer manuf, Model.Locker locker) {
this.Name = name;
this.Description = desc;
this.Remark = remark;
this.Value = value;
this.Categories = cat;
this.Manufacturer = manuf;
this.Locker = locker;
}
public Entity(int id, string name, string desc, string remark, int value, Model.CategoryWrapper cat, Model.Manufacturer manuf, Model.Locker locker) {
this.SqlID = id;
this.Name = name;
this.Description = desc;
this.Remark = remark;
this.Value = value;
this.Categories = cat;
this.Manufacturer = manuf;
this.Locker = locker;
}
}
我得到了一个 GridView(类型:实体)的 SelectedItem 并将它交给我的 Manipulation-View 实例化它的 ViewModel。在这个 ViewModel 中,实体被分为它的部分(例如制造商)和属性(例如 SelectedManufacturer)被设置。所有这些步骤都在视图构建之前执行(在 Initializecomponent 之前)。我认为通过这种方式,视图必须在初始化时获取选定的值 - 还是我错了?
更新 5:
我真的不知道为什么,但是当窗口初始化时设置制造商时,制造商对象的 PropertyChanged-Property 为空 - 当我通过选择一个项目来设置制造商时,该属性不为空。
【问题讨论】:
-
您尝试过使用转换器吗?我不是 100% 确定,但由于您使用的是不匹配的类型,这可能是问题所在。
-
我只记得“Manufacturer”是同一类型(除了Collection)。我会更新问题。
标签: c# wpf xaml binding combobox