Подтвердить что ты не робот

Почему привязка данных Windows Forms хочет установить мое вложенное свойство boolean databound, когда я создаю событие уведомления на родительском объекте?

Итак, вот какой-то контекст для моей проблемы, написанный как псевдо-С# -код (не стесняйтесь указывать на какую-либо ошибку): (Вы можете перейти непосредственно к 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 Forms в классах SomeForm или SomeControl. (ComplexObject.BoolProp является привязкой данных в обоих). Не стесняйтесь задавать больше вопросов о контексте.

Проблема: когда я делаю несколько (нескольких) уведомлений в классе 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

Почему программа хочет установить SomeBool на false? И как я могу это предотвратить?

4b9b3361

Ответ 1

Я переработал одиночный ViewModelClass в SomeFormViewModel и SomeControlViewModel и привязал их к их соответствующим классам.

Просто после этого проблема исчезла.

Мне все же хотелось бы лучше понять стек, который я поставил, но я предполагаю, что суть проблемы в том, что каждый BindingSource сохраняет свою собственную информацию об изменениях, внесенных в объект, и как они оба внесли изменения в один и тот же объект, они больше не знали, что происходит.

Ответ 2

Мой самый первый вопрос о переполнении стека был о поле в приложении Windows Forms, содержащем неожиданное значение, например ваше. Решение состояло в том, чтобы подождать, пока событие загрузки формы не будет запущено, чтобы настроить элементы GUI формы.

Я бы отложил настройку _model (включая создание его с помощью new) и других элементов GUI до тех пор, пока в обработчике события загрузки формы не будет.

HOWTO:

Добавить обработчик загрузки формы в Visual Studio:

  • Откройте форму в графическом представлении (например, дважды щелкните SomeForm.cs в обозревателе решений)

  • Двойной щелчок в форме, вне любых элементов управления или других элементов GUI (например, в строке заголовка). Это добавит код скелета для функции с именем SomeForm_Load, а строка this.Load += new System.EventHandler(this.SomeForm_Load); будет добавлена ​​SomeForm.Designer.cs.

Переместите установочный код на SomeForm_Load:

private void SomeForm_Load(object aSender, EventArgs anEvent)
{
    _model = new ViewModelClass;

    ViewModelClassBindingSource.DataSource = _model;
    SomeControl1.SetModel(_model);
}

Удалите "= new ViewModelClass" из объявления _model.

Ответ 3

Имела ту же проблему, при которой изменение вкладки в tabcontrol было бы reset для всех моих логических значений с привязкой к "false". Все небулевые значения были точными. Трассировка стека точно такая же, как OP.

Пробовал перемещаться по настройке viewmodel в Form_Load, как предложил Питер, но не повезло. В конце концов сдался и переместил всю привязку данных из кода к настройке в пользовательском интерфейсе, создав источник данных и установив привязку данных ко всем свойствам управления.