2010-08-09 26 views
8

Veritabanları uzantısı kullanarak güçlü yazılan Windows Forms veri bağlama arıyorum.Güçlü yazılan Windows Formları

txtBoundInt.DataBindings.Add<Contact> 
    (bindingSource, tb => tb.Text, contact => contact.Id); 

Ya da bu:

cboBoundSelectedItem.DataBindings.Add 
      <Contact, ComboBox> 
      (bindingSource, cbo => cbo.SelectedItem, con => con.ContactType) 

gibi görünüyor Şimdi bir böyle DataBinding kurabilirsiniz

using System; 
using System.Linq.Expressions; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public static Binding Add<T> 
     (this ControlBindingsCollection dataBindings, 
      object dataSource, 
      Expression<Func<Control, object>> controlExpression, 
      Expression<Func<T, object>> objectExpression) 
    { 
     return Add(dataBindings, dataSource, controlExpression, objectExpression, false); 
    } 

    public static Binding Add<T> 
     (this ControlBindingsCollection dataBindings, 
      object dataSource, 
      Expression<Func<Control, object>> controlExpression, 
      Expression<Func<T, object>> objectExpression, 
      bool formattingEnabled) 
    { 
     string controlPropertyName = ProcessExpression(controlExpression.Body); 
     string bindingTargetName = ProcessExpression(objectExpression.Body); 

     return dataBindings 
      .Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); 
    } 

    public static Binding Add<T, K> 
     (this ControlBindingsCollection dataBindings, 
      object dataSource, 
      Expression<Func<K, object>> controlExpression, 
      Expression<Func<T, object>> objectExpression) 
    { 
     return Add(dataBindings, dataSource, controlExpression, objectExpression, false); 
    } 

    public static Binding Add<T, K> 
     (this ControlBindingsCollection dataBindings, 
      object dataSource, 
      Expression<Func<K, object>> controlExpression, 
      Expression<Func<T, object>> objectExpression, 
      bool formattingEnabled 
     ) 
    { 
     string controlPropertyName = ProcessExpression(controlExpression.Body); 
     string bindingTargetName = ProcessExpression(objectExpression.Body); 

     return dataBindings.Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); 
    } 

    private static string ProcessExpression(Expression expression) 
    { 
     string propertyName; 
     if (expression is MemberExpression) 
     { 
      propertyName = ((MemberExpression) (expression)).Member.Name; 
     } 
     else if (expression is UnaryExpression) 
     { 
      propertyName = ((MemberExpression) ((UnaryExpression) (expression)).Operand).Member.Name; 
     } 
     else 
     { 
      throw new InvalidOperationException(
       "Unknown expression type error in DataBindingsExtensionMethods.Add<T, K>"); 
     } 
     return propertyName; 
    } 
} 

: Ben aşağıdaki gibi Xavier bu kadar aşağıdaki yardım var Gerçi bir sürü ifade dökümü devam ediyor. Daha iyi bir yolu var mı?


Düzenleme: Daha iyi bir yol buldunuz ama bunun cevabı bu soruyu değiştirmek için başı derde girdi - bu @Carl_G tarafından reproduced below bu.

+0

Lütfen sorunuzun cevabını değiştirmeyin. Bir çözüm bulduysanız, cevaplar bölümüne gitmesi gerekir. Bir çözüm için google bağlantılarına hızla göz atmaya çalışan bir kişiye, sorunun ne olduğunu bilmeden "Tamam, bir çözüm buldum" ya da ziyaretçinin sorununa uygulanabilir olup olmadığını değerlendirmek çok şaşırıyor. –

+0

Ah, kurallara göre oynamalıyız .. – stuartd

+0

C# 6'daki yeni nameof() işlevinin de bir dizgeyi kullanmaktan kaçınmak için kullanılabileceği belirtilmelidir. https://msdn.microsoft.com/en-us/library/dn986596.aspx –

cevap

6

Dönüş türünü nesneye ayarlamaya ne dersiniz?

public static Binding Add<T> 
    (this ControlBindingsCollection dataBindings, object dataSource, 
    Expression<Func<Control, object>> controlLambda, 
    Expression<Func<T, object>> objectLambda) { 
    string controlPropertyName = 
      ((MemberExpression)(controlLambda.Body)).Member.Name; 
    string bindingTargetName = 
      ((MemberExpression)(objectLambda.Body)).Member.Name; 

    return dataBindings.Add 
     (controlPropertyName, dataSource, bindingTargetName); 
} 
+0

Teşekkürler: Bu derleme, ancak bu çalışma zamanı hatası verir: 'System.Linq.Expressions.UnaryExpression' türünde nesne yazmak için 'Sistem' yazın .Linq.Expressions.MemberExpression'. – stuartd

+0

Hmm. ObjectLambda'yı bir UnaryExpression'a gönderebilirim, ama UnaryExpression'dan özellik adını nasıl alabileceğimi göremiyorum .. (controlLambda hala bir MemberExpression) – stuartd

+0

Yardımınız için çok teşekkürler, işte şimdi çivilenmiş. – stuartd

2

Birkaç aydır Stuart tarafından yayınlanan kodu kullanıyorum. Sana

public static class ControlExtensions { 

    /// <summary>Databinding with strongly typed object names</summary> 
    /// <param name="control">The Control you are binding to</param> 
    /// <param name="controlProperty">The property on the control you are binding to</param> 
    /// <param name="dataSource">The object you are binding to</param> 
    /// <param name="dataSourceProperty">The property on the object you are binding to</param> 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty)); 
    } 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled = false) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled); 
    } 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode); 
    } 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue); 
    } 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString); 
    } 
    public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString, IFormatProvider formatInfo) 
    where TControl :Control { 
     return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString, formatInfo); 
    } 

    public static class PropertyName { 
     public static string For<T>(Expression<Func<T, object>> property) { 
      var member = property.Body as MemberExpression; 
      if(null == member) { 
       var unary = property.Body as UnaryExpression; 
       if(null != unary) member = unary.Operand as MemberExpression; 
      } 
      return null != member ? member.Member.Name : string.Empty; 
     } 
    } 

} 
+2

Bu kod iyi çalıştı. Yine de küçük bir düzeltmeye ihtiyacı var. 'Kontrol' ile sınırlamak yerine, 'IBindableComponent' ile sınırlandırılmalıdır. 'DataBindings' özelliğine sahip doğru arabirim budur. – craigtadlock

4
(diğerleri çalışan bu çok yararlı bir şey elde daha kolay bulmalarını için onu burada post ediyorum) kullanmak isteyebilirsiniz veri bağlama senaryoları geri kalanı maç için birkaç aşırı yüklenmeleri eklemek yaptı

Soru sadece bir cevap içerecek şekilde düzenlendiğinden, bu cevabı buraya dahil ediyorum. Yazar muhtemelen the original question'u yalnız bırakmalı ve kendi sorusuna bir cevap yazmalıdır. Ama çok iyi bir çözüm gibi görünüyor.


Düzenleme: Ben (o author's site silindi) sadece bir tip şartname ihtiyaç duyduğundan sonunda in Google's cache bulundu bu çözümü tercih ederim. Orijinal yazarın neden sildiğini bilmiyorum.

// Desired call syntax: 
nameTextBox.Bind(t => t.Text, aBindingSource, (Customer c) => c.FirstName); 

// Binds the Text property on nameTextBox to the FirstName property 
// of the current Customer in aBindingSource, no string literals required. 

// Implementation. 

public static class ControlExtensions 
{ 
    public static Binding Bind<TControl, TDataSourceItem> 
     (this TControl control, 
     Expression<Func<TControl, object>> controlProperty, 
     object dataSource, 
     Expression<Func<TDataSourceItem, object>> dataSourceProperty) 
     where TControl: Control 
    { 
     return control.DataBindings.Add 
      (PropertyName.For(controlProperty), 
       dataSource, 
       PropertyName.For(dataSourceProperty)); 
    } 
} 

public static class PropertyName 
{ 
    public static string For<T>(Expression<Func<T, object>> property) 
    { 
     var member = property.Body as MemberExpression; 
     if (null == member) 
     { 
      var unary = property.Body as UnaryExpression; 
      if (null != unary) member = unary.Operand as MemberExpression; 
     } 
     return null != member ? member.Member.Name : string.Empty; 
    } 
} 
+3

SO'nın bir soru-cevap formatı vardır.Bu şekilde tasarlanmıştır, böylece aynı problem/soruya sahip kişiler sahip oldukları problem/soruları arayabilir ve daha sonra çözümlerden faydalanabilir veya önerebilir. Farklı stilistik tercihlere sahip farklı kullanıcılara açığım ancak orijinal sorunuzu tamamen sildiğinize kesinlikle katılmıyorum. Şimdi onun yerine koyduğunuz cevap, sorunun kendisine sağladığı tüm bağlamdan yoksundur. Bunu yapmak sadece SO'nın tasarımına karşı çıkmakla kalmaz, aynı zamanda diğerlerinin burada yer alan bilgilerden faydalanmasını da zorlaştırır. –

+0

Hayır, sadece doğru yerde bir cevabın ne olduğunu koydu. Yani birisi "tamam, bu sorunun ne hakkında olduğunu anlıyorum, şimdi iyi bir cevap olup olmadığını görmek için cevapları tarayacağım" diye eklediniz. –

+0

Orijinal sorunuzu en başa koyduğumu gördünüz mü? (Ve şimdi sadece cevap daha önce sahip olduğunuz gibi kaldı.) Belki de bunu geri aldığınızı düşünmüştüm, ama belki bir yönetici onu geri çevirdi. Bilmiyorum, sadece yardım etmeye çalışıyordum. –

İlgili konular