Weryfikacja na etapie kompilacji nazw właściwości wykorzystywanych w Windows Forms Data Binding

Kontrolki wizualne w technologii Windows Forms pozwalają tworzyć powiązanie pomiędzy właściwością kontrolki a właściwością obiektu będącego źródłem danych dla tej kontrolki.

1
2
3
4
5
6
7
class MyTextBox : TextBox
{
  public void Bind(object obj, string dataMember)
  {
    DataBindings.Add(new Binding("Text", obj, dataMember));
  }
}

Takie rozwiązanie działa bez zarzutu jednak ma pewną wadę – nazwa właściwości źródła danych przekazywana jest jako łańcuch znaków. Powoduje to sytuację, w której poprawność tego powiązania zweryfikujemy dopiero po uruchomieniu programu chociaż chciałoby się aby było to już na etapie kompilacji.

Aby osiągnąć mój cel postanowiłem skorzystać z możliwości jakie oferują wyrażenia lambda w ramach języka C#.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class MyTextBox1 : TextBox
{
  public void Bind<T>(T obj, Expression<Func<T, object>> dataMemberExpr)
  {
    string dataMember = GetDataMember(dataMemberExpr);
    DataBindings.Add(new Binding("Text", obj, dataMember));
  }

  private string GetDataMember(Expression<Func<T, object>> dataMemberExpr)
  {
    LambdaExpression expr = dataMemberExpr;
    Expression node = expr.Body;
    MemberExpression memberExpr = (MemberExpression)node;
    return memberExpr.Member.Name;
  }
}

Aby stworzyć powiązanie należy wywołać metodę Bind w następujący sposób:

1
2
3
4
5
6
7
8
9
class Person
{
  public string Name { get; set; }
}

Person p = new Person { Name = "Bob" };

MyTextBox1 myTextBox1 = new MyTextBox1();
myTextBox1.Bind(p, x => x.Name);