39

私はイベントベースのプログラミングに精通していません。基本的に、私はまだそれでつまずいています。何かを設定しようとしていますが、チュートリアルを使用しても、頭を包むことができません。私が(言葉で)やりたいことは次のとおりです。

  1. プロパティが変更されるデータオブジェクトがあります。プロパティのセッターでこれに気づき、プロパティが変更されたというイベントを発生させたいと思います。

  2. 他の場所(まったく別のクラス)で、このオブジェクトのプロパティが変更されたことを知り、何らかのアクションを実行したいと思います。

今、これは十分に一般的なシナリオであると確信していますが、私のgoogle-fuは私を失望させています。私は単にhttp://msdn.microsoft.com/en-us/library/ms743695.aspxを理解していません。

私はこれを持っています:

public class ChattyClass {
  private int someMember;

  public event PropertyChangedEventHandler PropertyChanged;

  public int SomeMember {
    get {
      return this.someMember;
    }
    set {
      if (this.someMember != value){
        someMember = value;
        // Raise event/fire handlers. But how?
      }
   }
}

public class NosyClass{
  private List<ChattyClass> myChatters;

  public void addChatter(ChattyClass chatter){
    myChatters.add(chatter);
    // Start listening to property changed events
  }

  private void listner(){
    // I want this to be called when the PropertyChangedEvent is called
    Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
  }
}

これを配線するにはどうすればよいですか?

リンクに戻るコメントについて:

私が見る例では:

protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

私が理解していないこと:

  • なぜこれはただ電話しないのですかPropertyChanged(this, new PropertyCHangedEventArgs(name))
  • PropertyChangedはどこに割り当てられますか?
  • 割り当てはどのように見えますか?
4

4 に答える 4

43

イベントを起動する必要があります。MSDNの例では、OnPropertyChangedこれを簡単に処理できるように(そして、コードの重複を避けるために)保護されたメソッドを作成しました。

// Create the OnPropertyChanged method to raise the event 
protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

このメソッドが行うことは、イベントハンドラーが割り当てられているかどうかを確認することです(割り当てられていない場合は、それを呼び出すだけで、が取得されますNullReferenceException)。割り当てられているものがある場合は、このイベントハンドラーを呼び出します。提供されるイベントハンドラーには、PropertyChangedEventHandlerデリゲートの署名が必要です。この署名は次のとおりです。

void MyMethod(object sender, PropertyChangedEventArgs e)

ここで、最初のパラメーターはオブジェクト型である必要があり、イベントを発生させるオブジェクトを表し、2番目のパラメーターにはこのイベントの引数が含まれます。この場合、独自のクラスがイベントを発生させthis、パラメーターとして指定しますsender。2番目のパラメーターには、変更されたプロパティの名前が含まれています。

イベントの発生に対応できるようにするには、イベントハンドラーをクラスに割り当てる必要があります。この場合、addChatterメソッドでこれを割り当てる必要があります。それとは別に、最初にハンドラーを定義する必要があります。これNosyClassを行うには、次のようなメソッドを追加する必要があります。

private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Console.WriteLine("A property has changed: " + e.PropertyName);
}

ご覧のとおり、このメソッドは前に説明した署名に対応しています。2番目のパラメーターでは、変更されたパラメーターの情報を見つけることができます。最後に、イベントハンドラーを追加します。今あなたのaddChatterメソッドでは、これを割り当てる必要があります:

public void AddChatter(ChattyClass chatter)
{
    myChatters.Add(chatter);
    // Assign the event handler
    chatter.PropertyChanged += new PropertyChangedEventHandler(chatter_PropertyChanged);
}

.NET / C#のイベントについて何か読むことをお勧めします:http://msdn.microsoft.com/en-us/library/awbftdfh。これを読んだり学んだりすると、物事がより明確になると思います。

すばやくテストしたい場合は、ここのpastebinにコンソールアプリケーションがあります(新しいコンソールアプリケーションにコピーして貼り付けるだけです)。

新しいバージョンのC#では、イベントハンドラーへの呼び出しをインライン化できます。

// inside your setter
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));

Fody PropertyChangedのようなものを使用して、必要なコードを自動的に生成することもできます(サンプルを含むGitHubページへのリンクにアクセスしてください)。

于 2012-08-20T09:23:20.123 に答える
14

探したリンクは、MVVMパターンとWPF用です。これは一般的なC#の実装ではありません。次のようなものが必要です。

public event EventHandler PropertyChanged;

    public int SomeMember {
        get {
            return this.someMember;
        }
        set {
            if (this.someMember != value) {
                someMember = value;
                if (PropertyChanged != null) { // If someone subscribed to the event
                    PropertyChanged(this, EventArgs.Empty); // Raise the event
                }
            }
        }

..。

public void addChatter(ChattyClass chatter) {
    myChatters.add(chatter);
    chatter.PropertyChanged += listner; // Subscribe to the event
}
// This will be called on property changed
private void listner(object sender, EventArgs e){
    Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
}

どのプロパティが変更されたかを知りたい場合は、イベント定義を次のように変更する必要があります。

public event PropertyChangedEventHandler PropertyChanged;

そして、呼び出しを次のように変更します。

public int SomeMember {
    get {
        return this.someMember;
    }
    set {
        if (this.someMember != value){
            someMember = value;
            if (PropertyChanged != null) { // If someone subscribed to the event
                PropertyChanged(this, new PropertyChangedEventArgs("SomeMember")); // Raise the event
            }
        }
   }

   private void listner(object sender, PropertyChangedEventArgs e) {
       string propertyName = e.PropertyName;
       Console.WriteLine(String.Format("Hey! Hey! Listen! a {0} of a chatter in my list has changed!", propertyName));
   }
于 2012-08-20T09:11:46.080 に答える
6

なぜこれはPropertyChanged(this、new PropertyCHangedEventArgs(name))を呼び出すだけではないのですか?

イベントにハンドラーをアタッチしている人がいない場合、PropertyChangedオブジェクトはを返すためnullです。したがって、呼び出す前にnullでないことを確認する必要があります。

PropertyChangedはどこに割り当てられますか?

「リスナー」クラス。

たとえば、他のクラスで書くことができます:

ChattyClass tmp = new ChattyClass();
tmp.PropertyChanged += (sender, e) =>
    {
        Console.WriteLine(string.Format("Property {0} has been updated", e.PropertyName));
    };

割り当てはどのように見えますか?

C#では、代入演算子+=-=イベントを使用します。次の記事を読んで、匿名メソッド形式(上記の例)と「古い」形式を使用してイベントハンドラーを作成する方法を理解することをお勧めします。

于 2012-08-20T09:23:09.707 に答える
3

元のコードを取得し、@ Styxxyの回答を組み込むと、次のようになります。

public class ChattyClass  : INotifyPropertyChanged 
{
  private int someMember, otherMember;

  public int SomeMember
  {
      get
      {
          return this.someMember;
      }
      set
      {
          if (this.someMember != value)
          {
              someMember = value;
              OnPropertyChanged("Some Member");
          }
      }
  }

  public int OtherMember
  {
      get
      {
          return this.otherMember;
      }
      set
      {
          if (this.otherMember != value)
          {
              otherMember = value;
              OnPropertyChanged("Other Member");
          }
      }
  }

  protected virtual void OnPropertyChanged(string propertyName)
  {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  }

  public event PropertyChangedEventHandler PropertyChanged;

}

public class NosyClass
{
    private List<ChattyClass> myChatters = new List<ChattyClass>();

    public void AddChatter(ChattyClass chatter)
    {
        myChatters.Add(chatter);
        chatter.PropertyChanged+=chatter_PropertyChanged;
    }

    private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("A property has changed: " + e.PropertyName);
    }
}
于 2015-08-18T13:36:49.107 に答える