[英]Why does Windows Forms databinding want to set my nested boolean databound property when I raise a notification event on the parent object?
OK, so here is some context for my problem, written as pseudo-C# code (feel free to point out any mistake): (You can jump directly to the stacktrace and read the context later.) 好的,所以这里是我的问题的一些上下文,写成伪C#代码(随意指出任何错误):(你可以直接跳转到堆栈跟踪并稍后阅读上下文。)
public class SomeForm {
private _model = new ViewModelClass
public void new() {
// Normal Winforms init omitted
ViewModelClassBindingSource.DataSource = _model;
SomeControl1.SetModel(_model);
}
}
public class SomeControl {
private _model = new ViewModelClass
internal void SetModel(ViewModelClass model) {
_model = model;
ViewModelClassBindingSource.DataSource = model;
ViewModelClassBindingSource.ResetBindings(true);
}
}
public class ComplexObject : IPropertyChanging, IPropertyChanged {
public property bool BoolProp {get; set;}
}
public class ViewModelClass : IPropertyChanged {
property IList<ComplexObject> ComplexObjects {get;}
property ComplexObject SelectedComplexObject {get; set;}
property Object SomethingNotNecessarilyRelated {get; set;}
private void NotifyPropertyChanged(string propName) {
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
All of the mentioned properties in these classes are databound in the Visual Studio 2008 Windows Forms designer, in the SomeForm
or in the SomeControl
classes. 这些类中提到的所有属性都是在Visual Studio 2008 Windows窗体设计器,
SomeForm
或SomeControl
类中进行数据绑定。 ( ComplexObject.BoolProp
is databound in both). (
ComplexObject.BoolProp
在两者中都是数据绑定的)。 Don't hesitate to ask more questions about the context. 不要犹豫,就上下文提出更多问题。
The problem: When I make some (bunch of) notifications in the ViewModelClass
class, there is some kind of knee-jerk reaction that sets ComplexObject.BoolProp
to false
, using that kind of stack trace: 问题:当我在
ViewModelClass
类中发出一些(一堆)通知时,会出现某种类型的下意识反应,使用这种堆栈跟踪将ComplexObject.BoolProp
设置为false
:
System.dll!System.ComponentModel.ReflectPropertyDescriptor.SetValue(object component = "Object Exposed in 'SelectedComplexObject'", object value = false) + 0x124 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindToObject.SetValue(object value) + 0x5d bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.PullData(bool reformat, bool force) + 0x15a bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingManagerBase.PullData(out bool success = true) + 0x6e bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingSource.ParentCurrencyManager_CurrentItemChanged(object sender = {System.Windows.Forms.CurrencyManager}, System.EventArgs e) + 0x54 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.OnCurrentItemChanged(System.EventArgs e) + 0x17 bytes
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.List_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + 0x3bc bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingSource.OnListChanged(System.ComponentModel.ListChangedEventArgs e) + 0x7e bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingSource.InnerList_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + 0x2e bytes
System.dll!System.ComponentModel.BindingList<System.__Canon>.OnListChanged(System.ComponentModel.ListChangedEventArgs e) + 0x17 bytes
System.dll!System.ComponentModel.BindingList<MyCompany.ViewModelClass>.Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + 0x176 bytes
[Native to Managed Transition]
[Managed to Native Transition]
MyCompany.Gui.exe!MyCompany.ViewModelClass.NotifyPropertyChanged(String propertyName = "SomethingNotNecessarilyRelated") Line 437 + 0x3c bytes Basic
Why does the program want to set SomeBool
to false
? 为什么程序想将
SomeBool
设置为false
? And how I can prevent that? 我怎么能防止这种情况?
My very first question on Stack Overflow was about a field in a Windows Forms application containing an unexpected value, like yours. 关于Stack Overflow的第一个问题是关于Windows Forms应用程序中包含意外值的字段,就像你的一样。 The solution was to wait until the form load event was fired to set up the GUI elements of the form.
解决方案是等到表单加载事件被触发以设置表单的GUI元素。
I would postpone setting up _model
(including constructing it with new
) and other GUI elements until in the handler for the form load event. 我会推迟设置
_model
(包括用new
构建它)和其他GUI元素,直到在表单加载事件的处理程序中。
HOWTO: 如何:
Add the form load handler in Visual Studio: 在Visual Studio中添加表单加载处理程序:
Open the form in the graphical view (for example, double-click SomeForm.cs
in Solution Explorer) 在图形视图中打开表单(例如,在解决方案资源管理器中双击
SomeForm.cs
)
Double click in the form, outside any controls or other GUI elements (for example, in the title bar). 双击表单,在任何控件或其他GUI元素之外(例如,在标题栏中)。 This will add skeleton code for a function named
SomeForm_Load
and the line this.Load += new System.EventHandler(this.SomeForm_Load);
这将为名为
SomeForm_Load
的函数添加框架代码,并添加this.Load += new System.EventHandler(this.SomeForm_Load);
will be added the SomeForm.Designer.cs
. 将添加
SomeForm.Designer.cs
。
Move the setup code to SomeForm_Load
: 将设置代码移动到
SomeForm_Load
:
private void SomeForm_Load(object aSender, EventArgs anEvent)
{
_model = new ViewModelClass;
ViewModelClassBindingSource.DataSource = _model;
SomeControl1.SetModel(_model);
}
Remove " = new ViewModelClass
" from the declaration of _model
. 从
_model
的声明中删除“ = new ViewModelClass
”。
I have refactored the single ViewModelClass
into SomeFormViewModel
and SomeControlViewModel
, and binding them to their respective classes. 我已将单个
ViewModelClass
重构为SomeFormViewModel
和SomeControlViewModel
,并将它们绑定到各自的类。
Simply doing that has made the issue disappear. 简单地这样做就会使问题消失。
I would still like a better understanding of the stacktrace that I put, though - I conjecture that the gist of the problem is that each BindingSource
maintains its own information of the changes made to the object - and as both of them made changes to the same object, they did not know what was happening anymore. 我仍然希望更好地理解我所放置的堆栈跟踪 - 我猜想问题的关键是每个
BindingSource
维护自己对对象所做更改的信息 - 并且因为它们都对它们进行了更改对象,他们不知道发生了什么事。
Had the same issue, where changing tab in a tabcontrol would reset all my databound boolean values to "false". 有同样的问题,在tabcontrol中更改选项卡会将我的所有数据绑定布尔值重置为“false”。 All non-boolean values were fine.
所有非布尔值都很好。 Stack trace showed exactly the same as OP.
堆栈跟踪显示与OP完全相同。
Tried moving around the setting of the viewmodel to Form_Load like Peter suggested, but no luck. 试图像Peter建议的那样将视图模型的设置移动到Form_Load,但没有运气。 Eventually gave up and moved all the databinding from code to setting it in the UI, by creating a data source and setting the databinding on all the control properties.
通过创建数据源并在所有控件属性上设置数据绑定,最终放弃并将所有数据绑定从代码移动到在UI中设置它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.