C# MVVM中的双向数据绑定问题
我正在尝试构建一个简单的C#/WinFoms项目,该项目根据结构使用模型视图模型设计模式: 两个UserControls和关联的ViewModels之间的数据绑定无法正常工作C# MVVM中的双向数据绑定问题,c#,winforms,design-patterns,mvvm,C#,Winforms,Design Patterns,Mvvm,我正在尝试构建一个简单的C#/WinFoms项目,该项目根据结构使用模型视图模型设计模式: 两个UserControls和关联的ViewModels之间的数据绑定无法正常工作 main表单包含两个用户控件(UC):UC\u创建,UC\u迭代。 每个UC包含一个组合框,该组合框连接到ViewModel_xxx中的关联属性,即 Uc_Create具有: this.comboBox1ComplexCreate.DataSource = oVM_Create.VM_Create_ListOfStrin
main表单
包含两个用户控件(UC):UC\u创建
,UC\u迭代
。
每个UC包含一个组合框,该组合框连接到ViewModel_xxx中的关联属性,即
Uc_Create具有:
this.comboBox1ComplexCreate.DataSource = oVM_Create.VM_Create_ListOfStringsInModel;
this.comboBox1ComplexIteration.DataSource = oVM_Iteration.VM_Iteration_ListOfStringsInModel;
Uc_迭代具有:
this.comboBox1ComplexCreate.DataSource = oVM_Create.VM_Create_ListOfStringsInModel;
this.comboBox1ComplexIteration.DataSource = oVM_Iteration.VM_Iteration_ListOfStringsInModel;
问题:
namespace Small_MVVM
{
public class Model
{
private static readonly object m_oLock = new object();
private static Model instance;
public List<string> simplelistOfStrings;
private Model()
{
simplelistOfStrings = new List<string>();
}
public static Model GetInstance()
{
if (instance == null)
{
lock (m_oLock)
{
if (instance == null)
{
instance = new Model();
}
}
}
return instance;
}
}
}
当我将元素添加到VM_Iteration_ListOfStringsInModel
中时,相应UC(comboBox1ComplexCreate
)和中的组合框中的列表已正确更改,但UC_Iteration
中的另一个组合框(Combox1ComplexIteration
)不正确
为什么
如果我将模型中的列表
更改为绑定列表
,则一切正常。我做错了什么
提前谢谢
型号:
namespace Small_MVVM
{
public class Model
{
private static readonly object m_oLock = new object();
private static Model instance;
public List<string> simplelistOfStrings;
private Model()
{
simplelistOfStrings = new List<string>();
}
public static Model GetInstance()
{
if (instance == null)
{
lock (m_oLock)
{
if (instance == null)
{
instance = new Model();
}
}
}
return instance;
}
}
}
如果您遵循MVVM模式,那么您应该使用
ObservableCollection
进行如下收集
private ObservableCollection<int> _intList;
public ObservableCollection<int> IntList
{
get
{
return _intList;
}
set
{
_intList= value;
_intList.CollectionChanged +=
new System.Collections.Specialized.NotifyCollectionChangedEventHandler
(MyProperty_CollectionChanged);
}
}
void MyProperty_CollectionChanged(object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyPropertyChanged("IntList");
}
private observeCollection\u intList;
公共可观测集合IntList
{
得到
{
返回_intList;
}
设置
{
_intList=值;
_intList.CollectionChanged+=
新System.Collections.Specialized.NotifyCollectionChangedEventHandler
(MyProperty_CollectionChanged);
}
}
void MyProperty\u CollectionChanged(对象发送方,
System.Collections.Specialized.NotifyCollectionChangedEventArgs(e)
{
NotifyPropertyChanged(“IntList”);
}
—表示一个动态数据收集,在添加、删除项目或刷新整个列表时提供通知
您还可以检查以下内容:我认为您的问题在于两个绑定列表之间没有链接 将项添加到VM_Iteration_ListofStringsModel时,更改将传播到绑定组合框和模型中的基础列表。但是模型中的列表无法将这些更改进一步传播到VM_Create_ListofStringsModel,因为它不支持此功能。VM_Create_ListofStringsModel将包含您添加到VM_Iteration_ListofStringsModel的项,但它不会引发ListChanged事件,因为模型中的列表会断开事件链。列表无法引发ListChanged事件。这就是BindingList存在的目的 正如您已经尝试过的,当您用BindingList替换模型中的列表时,它会起作用 因此,您已经提到的一种解决方案是,如果这是您的选项,那么另一种解决方案是对两个组合框只使用一个共享绑定列表
private void ListDemo()
{
var l = new List<string>();
l.Add("A");
BindingList<string> blist1 = new BindingList<string>(l);
BindingList<string> blist2 =new BindingList<string>(l);
blist1.ListChanged += Blist1_ListChanged;
blist2.ListChanged += Blist2_ListChanged;
blist1.Add("B");
// at this point blist1 and blist2 items count is 2 but only blist1 raised ListChanged
}
private void Blist2_ListChanged(object sender, ListChangedEventArgs e)
{
//No event fired here when adding B
}
private void Blist1_ListChanged(object sender, ListChangedEventArgs e)
{
// event fired when adding B
}
private void ListDemo()
{
var l=新列表();
l、 添加(“A”);
BindingList blist1=新的BindingList(l);
BindingList blist2=新的BindingList(l);
blist1.ListChanged+=blist1\u ListChanged;
blist2.ListChanged+=blist2\u ListChanged;
blist1.添加(“B”);
//此时,blist1和blist2项计数为2,但只有blist1项发生了更改
}
私有无效Blist2_ListChanged(对象发送方,ListChangedEventArgs e)
{
//添加B时,此处未激发任何事件
}
私有无效Blist1_ListChanged(对象发送方,ListChangedEventArgs e)
{
//添加B时激发的事件
}
通过初始化使用模型的绑定列表
的新对象来定义它们的属性(VM\u迭代
和VM\u创建
列表StringsinModel
),该对象使用模型。simplelistOfStrings
作为指定的源列表。因此,两个视图模型都有不同的对象,即模型中的ListofStringsModel,它们并不指向同一个对象
显然,您应该将simplelistOfStrings
属性定义为BindingList
,以便可以在视图
和代码隐藏
中建立双向数据绑定机制。但是,与在ViewModel\u Iteration
和ViewModel\u Create
ViewModels中定义新成员变量不同,我建议您更改属性定义,如下所示:
public BindingList<string> VM_Iteration_ListOfStringsInModel
{
get
{
return oModel.simplelistOfStrings;
}
set
{
oModel.simplelistOfStrings = value;
this.FirePropertyChanged(nameof(VM_Iteration_ListOfStringsInModel));
}
}
视图模型_创建
public BindingList<string> VM_Create_ListOfStringsInModel
{
get
{
return oModel.simplelistOfStrings;
}
}
VM_Create_ListOfStringsInModel.Clear();
VM_Create_ListOfStringsInModel.Add(item); // Or use AddRange to add Range.
尝试将数据源绑定到viewmodel属性
this.comboBox1ComplexCreate.Bindings.Add(“数据源”,oVM_Create,“VM_Create_ListOfStringsInModel”,true)
Grazie Fabio!不幸的是,它仍然不起作用:(您尝试过observablecollection吗?用两个视图共享一个视图模型是错误的做法。即使我们可以概念化或想象这一点。
public BindingList<string> VM_Create_ListOfStringsInModel
{
get
{
return oModel.simplelistOfStrings;
}
}
VM_Create_ListOfStringsInModel.Clear();
VM_Create_ListOfStringsInModel.Add(item); // Or use AddRange to add Range.