5

次のようなアクセサを持つイベントを起動するにはどうすればよいですか:

public event EventHandler CanExecuteChanged
    {
      add
      {
        CommandManager.RequerySuggested += value;
      }
      remove
      {
        CommandManager.RequerySuggested -= value;
      }
    }

通常のイベントであれば、次の方法で開始します。

CanExecuteChanged(sender, EventArgs..). 

しかし、ここでは機能しません-私はできることしかできません

CanExecuteChanged +=..

メソッドをアタッチしてイベントを実行しますが、起動できません。

また、件名に関するいくつかのドキュメントをいただければ幸いです。ありがとう。

編集 イベントは、WPF で ICommand を実装するクラスからのものです。表示するものはこれ以上ありません:)。いいえ - CommandManager.RequerySuggested(this, EventArgs.Empty); 動作しません。

EDIT2何を言うべきかわからない-追加メソッドが正しく呼び出されたとしても、ジョンの例はまだ機能しているはずです-イベントを呼び出そうとすると-それはnullです:|。おそらく、アクセサーを使用してイベントを削除します。

4

5 に答える 5

4

デリゲートと混同されたイベントがあると思います。イベントを公開しているクラスだけがそれを発生させることができます...他の人はそれを購読/購読解除することしかできません。イベントを宣言するクラス内からイベントを呼び出す場合は、通常のデリゲートのように機能する必要があります。

Events vs Delegatesで見つけた最高のページ。読んで..

もっと大きなスニペットを投稿できますか..何かがおかしいようです..

キラーアップデート

私はついにあなたの問題とそれを解決する方法を見たと思います。簡単な回答:独自のアクセサーを記述した場合、呼び出すデリゲートの名前がわかりません。そうしないと、コンパイラは既知の名前のプライベートデリゲートを追加するため、それを呼び出すことができます

このコード スニペットは、私の言いたいことを示しています。このMSDN の記事で光が見えてきました。いい質問ですね..30分無駄にしました。賛成:)

public class Hash1 
    {

        private EventHandler myHomeMadeDelegate;
        public event EventHandler FancyEvent
        {
            add
            {
                //myDelegate += value;
                myHomeMadeDelegate = (EventHandler)Delegate.Combine(myHomeMadeDelegate, value);
            }
            remove
            {
                //myDelegate -= value;
                myHomeMadeDelegate = (EventHandler)Delegate.Remove(myHomeMadeDelegate, value);
            }
        }
        public event EventHandler PlainEvent;


        public Hash1()
        {
            FancyEvent += new EventHandler(On_Hash1_FancyEvent);
            PlainEvent += new EventHandler(On_Hash1_PlainEvent);

            // FancyEvent(this, EventArgs.Empty);  //won't work:What is the backing delegate called? I don't know
            myHomeMadeDelegate(this, EventArgs.Empty); // Aha!
            PlainEvent(this, EventArgs.Empty);
        }

        void On_Hash1_PlainEvent(object sender, EventArgs e)
        {
            Console.WriteLine("Bang Bang!");
        }

        void On_Hash1_FancyEvent(object sender, EventArgs e)
        {
            Console.WriteLine("Bang!");
        }
}
于 2008-10-16T11:09:20.097 に答える
3

そのイベントは、別のイベントをサブスクライブしてサブスクライブ解除しているだけです。サブスクライバー (およびサブスクライバーのみ- 他のイベントとは別のものではなく) を呼び出したい場合は、サブスクライバーを個別に保持する必要があります。たとえば、コードを次のように変更できます。

private EventHandler canExecuteChanged;

public event EventHandler CanExecuteChanged
{
    add
    {
        CommandManager.RequerySuggested += value;
        canExecuteChanged += value;
    }
    remove
    {
        CommandManager.RequerySuggested -= value;
        canExecuteChanged -= value;
    }
}
于 2008-10-16T11:17:29.267 に答える
1

OK、そのイベントをトリガーしたい場合は、次のことを行う必要があることがわかりました。

CommandManager.InvalidateRequerySuggested();.
于 2008-10-16T11:42:33.710 に答える
0

うわー、ちょうど同様の問題がありました。私が理解するのを助けた答えはギシュの.

また、C#仕様http://www.microsoft.com/en-us/download/details.aspx?id=7029から、「10.8.1フィールドのようなイベント」の下に「フィールドのようなイベントをコンパイルするとき、コンパイラはデリゲートを保持するためのストレージを自動的に作成します。"

仕様にも次のように書かれています。

したがって、次の形式のインスタンス イベント宣言:

class X
{
   public event D Ev;
}

次と同等のものにコンパイルできます。

class X
{
   private D __Ev;  // field to hold the delegate

   public event D Ev {
      add {
         lock(this) { __Ev = __Ev + value; }
      }

      remove {
         lock(this) { __Ev = __Ev - value; }
      }
   }
}

以下のコードのようなことをすると、コンパイラはそれを正常にコンパイルします。

namespace ConsoleApplication1
{    
    class Program 
    {
        public event EventHandler ss;

        Program()
        {
            if (null != ss)
            {
                ss(this, EventArgs.Empty) ;

            }
        }

        static void Main(string[] args)
        {
            new Program();
        }
    }
}

上記の ss にアクセサを追加すると、コンパイルされません。

namespace ConsoleApplication1
{    
    class Program 
    {
        public event EventHandler ss
        {
            add { }
            remove { }
        }

        Program()
        {
            if (null != ss)
            {
                ss(this, EventArgs.Empty) ;

            }
        }

        static void Main(string[] args)
        {
            new Program();
        }
    }
}

ここでは 2 種類のイベントが示されています

  1. フィールドのようなイベント => 呼び出すことができます
  2. アクセサー付きのイベント => 呼び出すことができません (仕様でこれを見つけることができないのはなぜですか、おそらく私はそれを見逃していました) (これは Visual Studio 2005 でのみテストしており、仕様は最新のものだったと思います)
于 2012-11-29T02:25:53.463 に答える
0

基になるイベントを直接呼び出す必要があります。あなたの場合、これは次のようになります。

<blockquote>CommandManager.RequerySuggested(sender, EventArgs.…)</blockquote>

CommandManager/編集: わかりました、それがフレームワーク クラスである ことに気付きませんでした。この場合、あなたは明らかに私が提案したことをしたくありません。Jon の解決策は的を射ています。自分のイベントを追跡し、それを呼び出す必要があります (たとえば、デリゲートとして)。Jon の例に沿って、呼び出しは次のようになります。

canExecuteChanged(sender, EventArgs.Empty);
于 2008-10-16T11:08:47.383 に答える