1

DGVのデータを提供するBindingListとDataGridViewの間の双方向バインディングを実現しようとしています。一部の列は、基本となるリストの変更をまだ反映していないため、プロパティの変更を通知するためにプロパティ設定ツールを提供していないためだと思います。 Processプロパティの場合と同じ方法でRowsプロパティのセッターをコーディングするのではなく、もっと "エレガントな"ものを取得しようとしています...ユーティリティクラスのプロパティセッターの静的ユーティリティメソッドの使用方法

非常に興味深い書きかけに私はつまずいたよりエレガントなアプローチのために、私は(参照してください)、それの概念を実装しようとしている:ここで http://www.gavaghan.org/blog/2007/07/17/use-inotifypropertychanged-with-bindinglist/

はマイクの記事からコードである私は私のCBMIでUtilities.csとして設立(使用したいです。コモンプロジェクト):

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
namespace CBMI.Common 
{ 
public static class Utilities 
{ 
    public static bool Set<T>(object owner, string propName, 
     ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler) 
    { 
     // make sure the property name really exists 
     if (owner.GetType().GetProperty(propName) == null) 
     { 
      throw new ArgumentException("No property named '" + propName + "' on " + owner.GetType().FullName); 
     } 
     if (!Equals(oldValue, newValue)) // we only raise an event if the value has changed 
     { 
      oldValue = newValue; 
      if (eventHandler != null) 
      { 
       eventHandler(owner, new PropertyChangedEventArgs(propName)); 
      } 
     } 
    return true; // Please NOTE: I had to add this statement to avoid compile error: 
     // "not all code paths return a value". 
    } 
} 
} 

だから、私の最初の質問これについて:著者には返信の文がありませんでした。私はコンパイラのエラーを解決しました。私はイベントを推測しています.Handlerは実行して返します。これは著者の省略であり、メソッドがboolの戻り値の型を必要とするためtrueを返します。それは正しい仮定ですか?

私の第2の質問は、上記のヘルパーメソッドを使用しようとしたときに私が何であるかを示しています。私は上記のように、同じプロジェクト(および名前空間)にInputFileInfo.csと呼ばれる別のファイルにこのクラスをコード化されています:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
namespace CBMI.Common 
{ 
    public class InputFileInfo : INotifyPropertyChanged 
    { 
    private bool processThisFile; 
    public bool Process 
    { 
     get { return processThisFile; } 
     set 
     { 
     processThisFile = value; 
     this.NotifyPropertyChanged("Process"); 
     } 
    } 

    public string FileName { get; set; } 

    private long rowsReturned; 
    public long Rows 
    { 
     get { return rowsReturned; } 
     set 
     { 
     Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged); 
     } 

    } 
    public string Message { get; set; } 

    // constructor 
    public InputFileInfo(string fName) 
    { 
     Process = true; 
     FileName = fName; 
     Rows = 0; 
     Message = String.Empty; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(string name) 
    { 
     if (PropertyChanged != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(name)); 
    } 
    } 
} 

私はマイクのを使用しようとするところ、このクラスで2番目のプロパティのセッターがあります静的メソッド:

Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged); 

私はUtilities.Setを削除し、次のようにそれをコーディングする場合:私は、コンパイラのcomplaを取得..then

Set(this, "Rows", ref rowsReturned, value, PropertyChanged); 

その中には"という名前の 'Set'は現在のコンテキストに存在しません"

ユーティリティを使用してを追加しようとしました。ディレクティブしかし、それは問題を解決しませんでした。 REF T OLDVALUE、T newValueに
やSetメソッドが呼び出されというパラメータ:

最後に、私は、パラメータを理解していません。

これらのより高度なアイデアを使用できるように、誰かがこのコードに関するこれらの複数の混乱を助けてくれますか?

---- EDIT UPDATE ---- この2つの良い答えが私を助けてくれました。上記の元の投稿の「第2の質問」はまだ分かりません。これをパッケージ化する方法に関する「ベストプラクティス」を要求するコメントを追加したので、Mikeのオリジナル記事のように単純な呼び出し構文を使用できます。つまり、私はメソッド名だけで "ヘルパー"静的メソッドを呼び出すことを模索しています。私は次のように呼び出す方法を理解したい:

set 
{ 
    Set(this, "Rows", ref rowsReturned, value, PropertyChanged); 
} 

代わりとしてコーディングするので:

set 
{ 
    Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged); 
} 

私はUtilities.Setをコーディングすることによって、この作業を得たが、私は質問はにビットをモーフィング推測 - "静的メソッドとそれを呼び出す方法はどこに置くのですか?クラス名でそれらを「修飾」する必要はありませんか?私は、オブジェクトのインスタンスを必要としない一般的に有用な "ユーティリティ"型のメソッドをパッケージ化する方法を理解したいと思います。この場合、静的メソッドを設定して呼び出されたが、私のような他の静的メソッドを追加できるようにしたいと思います:

public static int HelpfulMethodXXXX(string s, int num) 

を私持っている唯一のクラスファイルを含む個別にコンパイルDLL(Vstudioプロジェクト)(S) 。最終的には、このクラスを他のアプリケーションで使用できると思っています。

彼らのように呼び出すことができることを、このような静的メソッドのこれらの並べ替えを宣言するのに最適な場所です。

int i = HelpfulMethodXXXX("Sample", testNumber); 

の代わり:

int i = ContainingClassName.HelpfulMethodXXXX("Sample", testNumber); 
+0

+1は肩をすくめていません:) – hoodaticus

答えて

1

1:すべての非空の方法が必要性を明示的なreturn文を持つ。

2:CMBI.Commonは名前空間です。 Utilitiesはあなたのクラスの名前です。 Set()はあなたのクラスの関数です。

Set()の呼び出しは、Utilitiesクラスのコンテキストでのみ意味があります。 Set()はグローバル名前空間の一部ではないため、Utilitiesクラスの外でSet()を呼び出す場合は、SomethingElse.Set()ではなくUtilities.Set()を指定する必要があります。 。 (ユーティリティ内では、コンパイラはSet()がUtilities.Set()を参照していることを理解しています)。

ステートメントの使用には、名前空間(CMBI.Common.Utilities)内のすべてのクラスを必要としない場合にのみ、名前空間(CMBI.Common)または名前空間内の特定のクラスを含めることができます。しかし、クラス関数をグローバル関数に変換することはできません。

3:Tは、この関数が動作する汎用型の名前を参照します。 http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx

ジェネリックスでは、コンパイル時の型の安全性を強制しながら、整数のコレクションと文字列のコレクションを同じコードで操作できます(コンパイラは整数を

refは、パラメータが参照として渡されることを意味し、関数の本体内でパラメータに加えられた変更は、関数の呼び出し元のコンテキストでパラメータの値に伝播されます。

+0

ありがとうございましたVladislav。 (1)私はreturn文を削除し、voidを返すようにメソッドを変更しました(これはコードを私が借りようとしている著者の見落としであったと思います)。 (3)私の質問に関連するジェネリックスに関する有用な要約のおかげで(2)ここでベストプラクティスは何ですか:CBMI.Commonと呼ばれる3つの別々のファイル(Utilities.cs、InputFileInfo.cs、DocMetaData.cs)を持っています。各ファイルは1つのパブリッククラス(クラス名はファイル名と同じです)を定義します。あなたの説明は、すべてのクラスを含む1つのファイル(biz.cs)だけを持つほうがよいかもしれないことを示唆しています。コメントしてください。 –

+0

さらに、チームで作業している場合、2人の開発者が大きなファイルをチェックアウトしている場合、変更によって競合が発生しない場合でも変更内容をマージする必要があります。また、複数のファイルで作業する方が簡単です。次に、1つのスーパーファイルで作業することです。 – Vladislav

+0

あなたはここで優れた点を作っています。私は毎日もっと勉強しています。上記のOPのEDIT-UPDATEに気付かれましたか?私のプログラムは現在動作していますが、私はまだUtilities.SetをSetとして呼び出すことはできません。私はそれと一緒に暮らすことができますが、EDIT-UPDATEでは問題を一般化しようとしました。私は今これを答えとしてチェックしていますが、これについてもう一度体重測定をしたいのであれば、私はそれを感謝したいと思います。君に乾杯! –

1
  • 今までに別の値を返すように表示されませんので、voidboolから変更する必要があり、戻り値の型のように見えます。

  • はい、Utilities.Setは正しい構文です。たとえば、Javaには静的なインポートにはアナログがありません。そのため、クラスでクラスを修飾する必要があります。 は、あなたが選択した場合、拡張メソッドを使用し、this.Set(...)のようなメソッドを呼び出すことができます。そのためには、ちょうどあなたのSet方法では、最初のパラメータの前にthisキーワードを追加します。

 

public static bool Set<T>(this object owner, string propName, 
    ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler) 
  • ref T oldValueは、あなたがそれをタイプTの変数を渡すことができることを意味しそれに古い値を書き込む(言い換えれば、値型の参照渡し)。この方法で、oldValueが何であったかを知ることができます。 (しかし、私にはoutのパラメータが意味をなさないと思われます)。

  • T newValueは、それを設定しようとしている新しい値です。 Tが何であるかを尋ねている場合は、ジェネリック型であり、の実際のタイプのプレースホルダーとして機能します。それはあなたがそれに渡す引数の型に基づいて自動的にどの型を調べます。 (あなたがそれstringを渡すと、Tは、あなたがstring代わりのTを使用しているかのよう機能します。)

  • valueは、あなたが定義するプロパティのsetアクセサに特別な意味を持っているC#で特別なキーワードです。これは、プロパティに割り当てる値です。

+0

大きな助けをいただきありがとうございました。戻り値の型をvoidに変更しました。私はUtilities.Setが有効である方法を見ることができますが、私は記事の著者(Mike)の指針に従おうとしていました。 「拡張メソッド」と構文の変更は、MikeのSet メソッドを実装するよりも「エレガント」に見えます。あなたはクラスごとに1つのファイルと1つのファイルでクラスをパッケージ化する "ベストプラクティス"を提案できますか(私のVladislavの答えに関するコメントを参照)。最後に、私の試みに適用されたジェネリックの簡潔な説明に感謝します。非常に役立ちます。 –

関連する問題