Hi,
>Hello,
>I use a business layer which I wan´t to bind to Windows Forms
>controls. I make heavy use of interfaces, I now I have a problem:
>I attached a sample Project to show the problem:
>When you test this little application, you will see the the databinding
>of comboBox1 will work fine (the setter of the property
>"ProfessionWorking" occurs), but the databinding of comboBox2 does not
>work (the setter or property "ProfessionNotWorking" does not occur).
>I found a reason why problem occurs: In the private Method
>System.Windows.Forms.Binding.ParseObject(), the type of the assigned
>value is compared with the type of the property, and here the
>Type.IsSubclassOf() Method is used. The problem is, that this Method
>does only work for classes, not for interfaces.
>I think this is a bug in the .NET Framework, they should use
>Type.IsAssignableFrom instead, then it work.
>So, what are my options?
I tried you code inside NET2.0 (assuming that's what you are using because
of the generic and partial keyword). There seems to be two problems:
1) The interface problem, yes there is a part inside ParseObject that uses
Type.IsSubclassOf but it's not used when you set FormattingEnabled to true.
The new formatting is used Formatter.FormatObject and it 'seems' to work for
interfaces.
2) At start the ComboBox selects the first item. Since the object
properties are null at start the ComboBox should be cleared, they are
initial out of sync with the DataSource, the ComboBox will write the first
item to the DataSource only when it gets validated (enter-leave). Setting
the Binding's DataSourceNullValue before adding the Binding to null in
combination with setting ComboBox.EnableFormatting to true seems to solve
the problem.
code for both problems:
// make sure ComboBox2.FormattingEnabled = true;
// enable formatting on Binding
Binding bnd = new Binding( "SelectedItem", m_Employee,
"ProfessionNotWorking", true);
// set datasourcenullvalue
bnd.DataSourceNullValue = null;
// add binding
ComboBox2.DataBindings.Add(bnd);
HTH,
Greetings
>Thanks for your answers.
>Dirk
Here is the sample:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace BindingProblem
{
public partial class Form1 : Form
{
public Form1 ()
{
InitializeComponent();
BindingList<IProfession> list = new
BindingList<IProfession>();
list.Add(new Profession("Butcher"));
list.Add(new Profession("Architect"));
list.Add(new Profession("Painter"));
list.Add(new Profession("Developer"));
BindingList<IProfession> list2 = new
BindingList<IProfession>();
list2.Add(new Profession("Butcher"));
list2.Add(new Profession("Architect"));
list2.Add(new Profession("Painter"));
list2.Add(new Profession("Developer"));
comboBox1.DataSource = list;
comboBox2.DataSource = list2;
comboBox1.DataBindings.Add("SelectedItem", m_Employee,
"ProfessionWorking");
comboBox2.DataBindings.Add("SelectedItem", m_Employee,
"ProfessionNotWorking");
}
Employee m_Employee = new Employee();
private ComboBox comboBox1;
private ComboBox comboBox2;
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen
gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor
geändert werden.
/// </summary>
private void InitializeComponent ()
{
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.comboBox2 = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comboBox1
//
this.comboBox1.DropDownStyle =
System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(12, 12);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 0;
//
// comboBox2
//
this.comboBox2.DropDownStyle =
System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox2.FormattingEnabled = true;
this.comboBox2.Location = new System.Drawing.Point(12, 40);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(121, 21);
this.comboBox2.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F,
13F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.comboBox2);
this.Controls.Add(this.comboBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// </summary>
[STAThread]
static void Main ()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public class Employee
{
Profession m_ProfessionNotWorking;
public IProfession ProfessionNotWorking
{
get
{
return m_ProfessionNotWorking;
}
set
{
m_ProfessionNotWorking = value as Profession;
}
}
Profession m_ProfessionWorking;
public Profession ProfessionWorking
{
get
{
return m_ProfessionWorking;
}
set
{
m_ProfessionWorking = value;
}
}
}
public class Profession : IProfession
{
private string profession;
public Profession (string arg)
{
profession = arg;
}
public override string ToString ()
{
return profession;
}
public string Description
{
get
{
return profession;
}
}
}
public interface IProfession
{
string Description
{
get;
}
}
}
Dirk - 18 Jan 2007 13:32 GMT
Hello Bart,
thank you for your help, your changes work. Perfect!
regards
Dirk