2009-09-11 10 views
7

私は最初のWPFプロジェクトに取り組んでおり、これまでに見たことが好きです。私が予想していたよりも多くの学習曲線がありましたが、WPFはかなりクールです。しかし、私はデータバインディングのコンセプトについて少し苦労しています。私が持っている具体的な質問の1つは、データバインディング宣言のリファクタリングを安全にする方法です。この例を考えてみましょう。WPFデータバインディングリファクタを安全にする方法を教えてください。

public class MyDataObject 
{ 
    public string FooProperty { get; set; } 
} 

void Bind() 
{ 
    var gridView = myListView.View as GridView; 
    gridView.Columns.Clear(); 
    gridView.Columns.Add(
    new GridViewColumn() 
     { 
     Header = "FooHeader", 
     DisplayMember = new Binding("FooProperty") 
     } 
    ); 
    List<MyDataObject> source = GetData(); 
    myListView.ItemsSource = source; 
} 

データオブジェクトのFooPropertyの名前を変更するとどうなりますか?バインディングはテキストのみで宣言されているため、データバインディングは無効で、コンパイルエラーは発生しません。バインディングをもう少しリファクタリングで安全にする方法はありますか?

答えて

3

あなたはむしろ、直接名前を使用するよりも、プロパティ名を表現するためにラムダ式を使用することができます。

protected static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
    { 
     if (expression.NodeType == ExpressionType.Lambda && expression.Body.NodeType == ExpressionType.MemberAccess) 
     { 
      PropertyInfo prop = (expression.Body as MemberExpression).Member as PropertyInfo; 
      if (prop != null) 
      { 
       return prop.Name; 
      } 
     } 
     throw new ArgumentException("expression", "Not a property expression"); 
    } 

あなたはそのようにそれを使用します。

... 
DisplayMember = new Binding(GetPropertyName((MyDataObject o) => o.FooProperty)) 
... 

OK、それは少し冗長です...何かを短くしたい場合は、ヘルパーメソッドを作成することもできます:

public Binding CreateBinding<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
{ 
    return new Binding(GetPropertyName(expression)) 
} 

... 
DisplayMember = CreateBinding((MyDataObject o) => o.FooProperty) 
... 

それwあなたがプロパティの名前を変更した場合、リファクタリングはうまく動作するはずです(ただし、XAMLは例外です...)

+0

非常に賢い。はい、xamlはまだ問題ですが、少なくとも私の直接のシナリオでは、現時点では問題ではないので、カラムを動的に作成する必要があります。ありがとう! –

0

あなたはあなたの財産の名前を決定するためにリフレクションを使用することができます。もちろん、これはあなたがクラスごとに結合つ以上を持っている場合は問題があるので、おそらくさらに取得する(リフレクション経由でも利用可能です)カスタム属性を使用すると、指定されたプロパティがにバインドする必要があることを正しい結合フィールドとして「ヒント」。非常によくちょうどアプリケーションの別の部分に非refactorable魔法の文字列を再配置するに終わる可能性があり

しかし、私はこれを試してみましたし、それが仕事持っていたと言うことはできません。

+0

リファクタリングは設計時に発生するものですが、リフレクションは実行時に発生します。 –

+0

もちろん、私が質問を理解しているように、リファクタリングはバインディングのFooPropertyの「魔法の文字列」を捕捉しないだろうから、そういうわけではありません。だから、実際にはリファクタリングは実行時に起こるかもしれません。その財産は変化し、拘束力はないだろう。リフレクションを介して実行時に正しい文字列を取得することによって、常に最新の世界を見て、あなたがすべての定数を変更したことを確認することに依存しません。 – Mikeb

+0

@Mikeb - 使用するリファクタリングツールによって異なります。 –

2

リファクタリングは、コード内の特定のシンボル(C位、XAML、設定などが...)と改名された識別子を表す場合認識するツールのサポートに依存しています。あなたが与える例で

は、 "FooProperty"文字列リテラルは、100%WPFや他のフレームワーク内の他のすべてのタイプ GridViewの内部の仕組みの特別な知識がなくても、拡張子によって MyDataObjectに属するものとして解釈することができませんでした。

しかし、のDataTemplateで、それは99%で確認することが可能です:私が使う(と誓う)と呼ばれるIDEプラグインを

<DataTemplate DataType="{x:Type local:MyDataObject}"> 
    <TextBlock Text="{Binding Path=FooProperty}" /> 
</DataTemplate> 

ReSharper(別名R#)、これらの種類については非常に知的です物事のFooPropertyの名前を変更すると、R#はそのプロパティの名前を自動的に変更します。あなたの例では

、プロパティの名前を変更した場合、R#がまだ使用であろう。リテラル内の文字列のすべてのインスタンス(あなたのケース)とコメントを検索します(コードをコメントアウトしてコメントを外してから後でコメントを外すことができる場合は非常に便利です)。コンテキスト内の各リテラルを表示するツリービューが用意されています。先に進む前に、個々の用途/ファイル/フォルダ/プロジェクトをチェック/選択解除することができます。予算が許せば

、R番号を取得します。あなたの予算が許せない場合は、試用版をダウンロードし、それを終えると、予算に余裕ができます。あなたの学習経験を向上させるために、ショートカットキーのコピーを印刷してください。

+0

お勧めです。 –

関連する問題