Monthly Archives: November 2006

Master-Slave for databound ComboBoxes

In most examples on the Internet you’ll find that the Master has a property that returns the allowed Slaves. Here’s an example that does not require such a property. Let’s start with a simple class that represents a Person.

public class Person
{
 private string name;

 public Person(string name)
 {
  this.name = name;
 }

 public string Name
 {
  get { return this.name; }
  set { this.name = value; }
 }
}

And now we define a class to hold the choosen Master and Slave persons.

public class MasterSlave
{
 private Person master;
 private Person slave;

 public MasterSlave()
 {
  Person[] masters = this.GetMasters();
  this.master = masters[0];

  Person[] slaves = this.GetSlaves(this.master);
  this.slave = slaves[0];
 }

 public Person Master
 {
  get { return this.master; }
  set { this.master = value; }
 }

 public Person Slave
 {
  get { return this.slave; }
  set { this.slave = value; }
 }

 public Person[] GetMasters()
 {
  List<person> masters = new List<person>();
  masters.Add(new Person("master1"));
  masters.Add(new Person("master2"));
  return masters.ToArray();
 }

 public Person[] GetSlaves(Person person)
 {
  List<person> slaves = new List<person>();

  switch (person.Name)
  {
   case "master1":
    slaves.Add(new Person("master1-slave1"));
    slaves.Add(new Person("master1-slave2"));
    break;
   case "master2":
    slaves.Add(new Person("master2-slave1"));
    slaves.Add(new Person("master2-slave2"));
    slaves.Add(new Person("master2-slave3"));
    break;
  }
  return slaves.ToArray();
 }
}

And now we can hook these objects to your Form.

public partial class Form1 : Form
{
 public Form1()
 {
  InitializeComponent();

  MasterSlave masterSlave = new MasterSlave();

  BindingSource masterBindingSource = new BindingSource();
  masterBindingSource.DataSource = masterSlave.GetMasters();
  masterBindingSource.CurrentChanged += new EventHandler(masterBindingSource_CurrentChanged);

  this.comboBoxMaster.DataSource = masterBindingSource;
  this.comboBoxMaster.DisplayMember = "Name";
  this.comboBoxMaster.DataBindings.Add("SelectedItem", masterSlave, "Master");

  BindingSource slaveBindingSource = new BindingSource();
  slaveBindingSource.DataSource = masterSlave.GetSlaves(masterBindingSource.Current as Person);

  this.comboBoxSlave.DataSource = slaveBindingSource;
  this.comboBoxSlave.DisplayMember = "Name";
  this.comboBoxSlave.DataBindings.Add("SelectedItem", masterSlave, "Slave");
 }

  private void masterBindingSource_CurrentChanged(object sender, EventArgs e)
  {
   BindingSource masterBindingSource = this.comboBoxMaster.DataSource as BindingSource;
   Person master = masterBindingSource.Current as Person;

   BindingSource slaveBindingSource = this.comboBoxSlave.DataSource as BindingSource;
   MasterSlave masterSlave = this.comboBoxSlave.DataBindings["SelectedItem"].DataSource as MasterSlave;
   slaveBindingSource.DataSource = masterSlave.GetSlaves(master);
  }
 }
}

A better look at the Foreach statement

Earlier this week i was a bit surprised that the following code compiled without errors or warning messages. I expected at least a warning that i was trying to assign a double value to an integer parameter:

static void Main(string[] args)
{
 double[] values = new double[] { 1.1, 2.2, 3.3, 4.4, 5.5 };

 Console.WriteLine("foreach with int:");

 // happily iterate over the double values as if they are ints...
 // this outputs the lines 1, 2, 3, 4 and 5.
 foreach (int value in values)
 {
  Console.WriteLine(value);
 }
}

So i decided to dive into the C# Language Specification (Section 15.8.4 The foreach statement) where i found the following:

A foreach statement of the form foreach (V v in x) embedded-statement is then expanded to:

{
 E e = ((C)(x)).GetEnumerator();
 try {
  V v;
  while (e.MoveNext()) {
   v = (V)(T)e.Current;
   embedded-statement
  }
 }
 finally {
  … // Dispose e
 }
}

Querying Active Directory

A while ago i wanted to figure out which demo accounts i had already created in my Active Directory. Since i was smart enough to give them all a description ‘Demo User’ this was easily done as following:

using( DirectoryEntry directoryEntry = new DirectoryEntry() )
{
 using( DirectorySearcher directorySearcher = new DirectorySearcher() )
 {
  directorySearcher.Filter = "(&(objectClass=user)(description=Demo User))";
  directorySearcher.SearchScope = SearchScope.Subtree;
  directorySearcher.Sort = new SortOption("displayname", SortDirection.Ascending );

  SearchResultCollection results = directorySearcher.FindAll();
  foreach( SearchResult result in results )
  {
   ResultPropertyCollection propertyCollection = result.Properties;
   Console.WriteLine( "{0}: {1}", propertyCollection["displayname"][0].ToString(), propertyCollection["description"][0].ToString() );
   }
  }
}