Warum funktioniert die ComboBox.SelectedValue-Binding-Kontext wird deaktiviert, wenn BindingList verpasst?
Ich habe einige Logik in die business-Schicht, die die Grenzen der ComboBox Optionen gemäß Eingänge, so muss ich ändern Sie die Werte in der zugrunde liegenden BindingList. Aber wenn die Liste verändert wird, die zwei-Wege-Bindung wird Einbahnstraße von der UI zur Einheit nur.
_mComboBox.DataBindings.Add("SelectedValue", _mEntity, "WifeCount");
Vollständigen code, mit dem problem-in die Schaltfläche "zuweisen" klicken Sie auf " handler:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace EnumDataBinding
{
public partial class Form1 : Form
{
ComboBox _mComboBox = new ComboBox();
Button _mCheckButton = new Button();
Button _mAssignButton = new Button();
BindingList<OptionValue> _mBindingList = new BindingList<OptionValue>();
List<OptionValue> _mCacheList = new List<OptionValue>();
Entity _mEntity = new Entity();
public Form1()
{
InitializeComponent();
//create a reset button
_mCheckButton.Size = new Size(100, 30);
_mCheckButton.Text = "Check";
_mCheckButton.Location = new Point(100, 100);
_mCheckButton.Click += new EventHandler(_mCheck_Click);
//create assignment button
_mAssignButton.Size = new Size(100, 30);
_mAssignButton.Text = "Assign";
_mAssignButton.Location = new Point(100, 135);
_mAssignButton.Click += new EventHandler(_mAssignButton_Click);
//create a combo box
_mComboBox = new ComboBox();
_mComboBox.Size = new System.Drawing.Size(300, 30);
_mComboBox.Location = new Point(100, 200);
this.Controls.AddRange(new Control[] {
_mComboBox,
_mCheckButton,
_mAssignButton
});
//fill the bindinglist
_mBindingList.Add(new OptionValue("One", 1M));
_mBindingList.Add(new OptionValue("Two", 2M));
_mBindingList.Add(new OptionValue("Three", 3M));
_mCacheList.Add(new OptionValue("One", 1M));
_mCacheList.Add(new OptionValue("Two", 2M));
_mCacheList.Add(new OptionValue("Three", 3M));
}
void _mAssignButton_Click(object sender, EventArgs e)
{
//reset options
_mBindingList.Clear();
foreach (var o in _mCacheList)
_mBindingList.Add(o);
//EXPECTED: Update ComboBox.SelectedValue and ComboBox.Text
//RESULT: Does not happen.
_mEntity.WifeCount = 3M;
this.Text = string.Format("SelectedValue: {0}; WifeCount: {1}", _mComboBox.SelectedValue, _mEntity.WifeCount);
}
private void PrepareComboBox(ComboBox combobox, BindingList<OptionValue> list)
{
combobox.DropDownStyle = ComboBoxStyle.DropDown;
combobox.AutoCompleteSource = AutoCompleteSource.ListItems;
combobox.AutoCompleteMode = AutoCompleteMode.Suggest;
combobox.DataSource = new BindingSource() { DataSource = list };
combobox.DisplayMember = "Display";
combobox.ValueMember = "Value";
combobox.Text = string.Empty;
combobox.SelectedText = string.Empty;
}
protected override void OnLoad(EventArgs e)
{
//combo box datasource binding
PrepareComboBox(_mComboBox, _mBindingList);
//entity data binding
_mComboBox.DataBindings.Add("SelectedValue", _mEntity, "WifeCount", false);
base.OnLoad(e);
}
void _mCheck_Click(object sender, EventArgs e)
{
this.Text = string.Format("SelectedValue: {0}; WifeCount: {1}", _mComboBox.SelectedValue, _mEntity.WifeCount);
}
}
public class Entity : INotifyPropertyChanged
{
decimal _mWifeCount;
public decimal WifeCount { get { return _mWifeCount; } set { _mWifeCount = value; OnPropertyChanged("WifeCount"); } }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class OptionValue
{
string _mDisplay;
object _mValue;
public string Display { get { return _mDisplay; } set { _mDisplay = value; } }
public object Value { get { return _mValue; } set { _mValue = value; } }
public OptionValue(string display, object value)
{
_mDisplay = display;
_mValue = value;
}
}
}
Update: Hinzufügen einer Ereignisprozedur für das Kombinationsfeld scheint zu funktionieren:
void _mComboBox_SelectedValueChanged(object sender, EventArgs e)
{
var binding = (sender as Control).DataBindings["SelectedValue"];
if (binding != null)
binding.WriteValue();
this.Text = string.Format("SelectedValue: {0}; WifeCount: {1}", _mComboBox.SelectedValue, _mEntity.WifeCount);
}
- Ich denke, die wichtigere Frage ist WifeCount?
- lols.. ich habe gerade zufällig eine variable auszuwählen. Soll LifeCount aber ich bin gewöhnt, umbenennen, alles auf SO.
- In welche Richtung wird es nicht funktioniert?
- Für mich ist es die Einstellung, die den Wert der Person. D. H. klicken auf die Schaltfläche "zuweisen".
- wow.. schön upvotes. aber die Menschen sollten nicht nur hierher kommen, um zu überprüfen, auf die Frau zählen!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, dass, um zu haben, zwei-Wege-Bindung, Sie zur Implementierung der INotifyPropertyChanged-Schnittstelle für das element, das in die verbindliche Liste. Der Grund dafür ist, dass die BindingList verwendet wird als die Datenquelle, die nicht wissen, wenn eines der Elemente verändert haben, es sei denn, die Elemente, pass auf, die Informationen. Allerdings kann es immer noch passieren auf Ereignisse in Bezug auf die Elemente Hinzugefügt und entfernt werden (vorausgesetzt, Sie geben AllowRemove/AllowNew-Eigenschaft auf true), weil das Ereignis in den Bereich der Liste, nicht die einzelnen Elemente.
Edit: Bah! Die Waffe sprang und wusste nicht, Lesen Sie die Frage/problem gründlich. Hier ist das Problem, das hinzufügen von databindings anscheinend standardmäßig eine ein-Weg-Bindung (initial binden NUR der Wert). Was Sie tun müssen, ist geben Sie die DataSourceUpdateMode, wenn Sie den databinding an combobox:
Gerade getestet, mit alles andere gleich geblieben und es hat funktioniert. Lassen Sie mich wissen!
Edit: Also es funktioniert nicht (ich war nicht das löschen der Liste), und ich habe herausgefunden, warum. Also das ist, was ich bin zu bemerken. Für einige Grund, der verbindliche Rahmen für die Entität wird immer gelöscht, wenn die zugrunde liegende Datenquelle ist immer verändert. Nicht ganz sicher warum, aber ich habe definitiv festgestellt, dass, dass ist das Problem. Die Art, wie ich herausfand, war das hinzufügen einer Uhr auf der binding-Kontext der _mComboBox für die Person:
_mComboBox.BindingContext[_mEntity]
und behalten den überblick über die Bindungen zählen. Sobald ein neues Element Hinzugefügt wird, die _mBindingList, es scheint zu mucken mit der internen databindings der ComboBox, die letztlich fällt die Bindung für das Unternehmen.WifeCount -> ComboBox.SelectedValue-Bindung, die wir eingerichtet. Habe versucht, verschiedene Dinge, aber ich bin mir nicht ganz sicher, WARUM der PropertyManager fällt die Bindung, wenn die zugrunde liegende Datenquelle ändert._mBindingList.RaiseListChangedEvents = false
vor.Clear()
und_mBindingList.RaiseListChangedEvents = true
nach_mEntity.WifeCount = 3M;
scheint zu funktionieren, obwohl es ist nicht abzusehen, ob da noch mehr versteckte Probleme.Nun, dass ich verstehe, was Sie versuchen zu tun, ich denke, das ist wahrscheinlich eine praktikable Lösung:
Zwei-Wege-Bindung ist in Ordnung, so wie Sie haben es aber löschen der datasource der combobox tötet die databindings als gut. Wenn Sie gehen, um die änderung der verbindlichen Liste sollten Sie vielleicht neu binden Sie alle Zeit der Datenquelle änderungen :