代码之家  ›  专栏  ›  技术社区  ›  Jean Hominal

在父对象上引发通知事件时,Windows窗体数据绑定为什么要设置嵌套的布尔数据绑定属性?

  •  11
  • Jean Hominal  · 技术社区  · 14 年前

    好的,下面是我问题的一些上下文,写为伪C代码(请随意指出任何错误):(您可以直接跳到stacktrace,稍后再阅读上下文。)

    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));
        }
    }
    

    这些类中提到的所有属性都是在Visual Studio 2008 Windows窗体设计器中数据绑定的。 SomeForm 或者在 SomeControl 课程。( ComplexObject.BoolProp 两者都是数据绑定的)。不要犹豫,多问一些有关上下文的问题。

    问题是:当我在 ViewModelClass 同学们,有种下意识的反应 complexObject.boolprop(复杂对象.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
    

    程序为什么要设置 SomeBool ?我怎么能阻止呢?

    3 回复  |  直到 7 年前
        1
  •  4
  •   Peter Mortensen icecrime    14 年前

    关于堆栈溢出的第一个问题是关于Windows窗体应用程序中包含意外值的字段,如您的字段。解决方案是等待直到触发窗体加载事件以设置窗体的GUI元素。

    我会推迟设置 _model (包括用 new )以及其他GUI元素,直到在表单加载事件的处理程序中。

    豪托:

    在Visual Studio中添加表单加载处理程序:

    1. 在图形视图中打开表单(例如,双击 SomeForm.cs 在解决方案资源管理器中)

    2. 在表单中的任何控件或其他GUI元素(例如,在标题栏中)外双击。这将为名为 SomeForm_Load 还有那条线 this.Load += new System.EventHandler(this.SomeForm_Load); 将添加 SomeForm.Designer.cs .

    将设置代码移动到 某种形式的负载 :

    private void SomeForm_Load(object aSender, EventArgs anEvent)
    {
        _model = new ViewModelClass;
    
        ViewModelClassBindingSource.DataSource = _model;
        SomeControl1.SetModel(_model);
    }
    

    删除“ = new ViewModelClass “从 γ模型 .

        2
  •  0
  •   Jean Hominal    14 年前

    我把单曲改了 ViewModelClass 进入之内 SomeFormViewModel SomeControlViewModel 并将它们绑定到各自的类中。

    仅仅这么做就让问题消失了。

    不过,我还是希望更好地理解我所放置的stacktrace,我猜想问题的要点是 BindingSource 维护它自己对对象所做更改的信息——当他们两个都对同一个对象进行了更改时,他们不知道接下来会发生什么。

        3
  •  0
  •   johnbt    7 年前

    同样的问题是,在TabControl中更改选项卡会将所有数据绑定布尔值重置为“false”。所有非布尔值都很好。堆栈跟踪显示与op完全相同。

    像彼得建议的那样,尝试在视图模型的设置周围移动以形成负载,但没有运气。最终放弃并将所有数据绑定从代码移动到用户界面中的设置,方法是创建数据源并在所有控件属性上设置数据绑定。