简体   繁体   English

启动具有访问者的事件

[英]Launch an event that has accessors

How can I launch an event that has accessors like this : 如何启动具有以下访问器的事件:

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

If it were a normal event I would launch it by: 如果这是正常事件,我会通过以下方式启动它:

CanExecuteChanged(sender, EventArgs..). 

But here it doesn't work - I can only do 但在这里它不起作用 - 我只能这样做

CanExecuteChanged +=..

to attach a method do the event - but I can't Launch it. 附加方法做事件 - 但我无法启动它。

Also some documentation on the subject would be appreciated. 此外,一些关于这个主题的文件将不胜感激。 Thanks. 谢谢。

EDIT The event is from class implementing ICommand in WPF. 编辑该事件来自在WPF中实现ICommand的类。 there's nothing more to show :). 没有什么可以显示:)。 And no - the CommandManager.RequerySuggested(this, EventArgs.Empty); 并且没有 - CommandManager.RequerySuggested(this,EventArgs.Empty); doesn't work. 不起作用。

EDIT2 Not sure what to say - Jon's example should have worked yet even if the add method is called correctly - when I try to call the event - it's null :|. EDIT2不知道该说些什么 - 即使正确调用add方法,Jon的例子也应该有效 - 当我尝试调用事件时 - 它是null:|。 I probably will drop events with accessors. 我可能会删除带有访问器的事件。

I think you have events confused with delegates. 我认为你有与代表混淆的事件。 Only the class exposing the event can raise it... Others can only subscribe-unsubscribe to it. 只有暴露事件的类才能引发它......其他人只能订阅 - 取消订阅它。 If you are invoking the event from within the class declaring the event, it should work like a regular delegate. 如果要从声明事件的类中调用事件,它应该像常规委托一样工作。

The best page I could find on Events vs Delegates . 我可以在Events vs Delegates上找到的最佳页面。 Read up.. 读起..

Can you post a bigger snippet.. something seems amiss.. 你可以发一个更大的片段......似乎有些不对劲......

Killer Update 杀手更新

I think I finally see your problem and how to solve it. 我想我终于看到了你的问题以及如何解决它。 Short Answer: It does not know the name of delegate to invoke if you write your own accessors. 简答: 如果您编写自己的访问器,它不知道要调用的委托的名称。 If you don't.. the compiler adds the private delegate of known name and hence is able to invoke it 如果你不这样做......编译器会添加已知名称的私有委托,因此可以调用它

This code snippet shows what I mean. 这段代码显示了我的意思。 This MSDN article showed me the light . 这篇MSDN文章向我展示了光明 Great question dude.. I lost 30 mins. 很棒的问题伙计......我失去了30分钟。 Upvoted :) Upvoted :)

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!");
        }
}

That event is just subscribing to and unsubscribing from another event. 该事件只是订阅和取消订阅另一个事件。 If you want your subscribers (and only your subscribers - not separate ones to the other event) to be invoked, you'll need to keep hold of your subscribers separately. 如果您希望调用您的订阅者(并且只有您的订阅者 - 而不是与其他活动分开的订阅者),则需要单独保留您的订阅者。 For instance, you could change the code to something like: 例如,您可以将代码更改为:

private EventHandler canExecuteChanged;

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

好的,我发现如果我想触发那个事件,你必须这样做:

CommandManager.InvalidateRequerySuggested();.

wow, just had similar problems. 哇,刚才有类似的问题。 The answer that helped me understand is somewhat like Gishu's . 帮助我理解的答案有点像Gishu的

Also from the C# specs, http://www.microsoft.com/en-us/download/details.aspx?id=7029 , under "10.8.1 Field-like events" it says "When compiling a field-like event, the compiler automatically creates storage to hold the delegate," 同样来自C#规范, http://www.microsoft.com/en-us/download/details.aspx?id = 7029,在“10.8.1类字段事件”下,它说“在编译类似字段的事件时” ,编译器自动创建存储来保存委托,“

specs also says: 规格还说:

Thus, an instance event declaration of the form: 因此,表单的实例事件声明:

class X
{
   public event D Ev;
}

could be compiled to something equivalent to: 可以编译成相当于:

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; }
      }
   }
}

If you do something like the code below, the compiler compiles it successfully: 如果您执行类似下面的代码,编译器会成功编译它:

namespace ConsoleApplication1
{    
    class Program 
    {
        public event EventHandler ss;

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

            }
        }

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

And if you add accessors to ss above, it will NOT compile: 如果你向上面的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();
        }
    }
}

There are two kinds of events demonstrated here 这里展示了两种事件

  1. Field-like events => we can invoke 类似字段的事件=>我们可以调用
  2. events with accessors => we cannot invoke (cannot find this in specs why, maybe I missed it)(and was only testing this on Visual Studio 2005, and the specs was the latest, I guess) 带有访问者的事件=>我们无法调用(在规格中找不到这个,为什么,也许我错过了)(并且只在Visual Studio 2005上进行了测试,并且规格是最新的,我猜)

You've got to invoke the underlying events directly. 您必须直接调用基础事件。 In your case, it looks as though this would be: 在您的情况下,看起来好像这样:

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

/EDIT: Ok, I didn't notice that CommandManager is a framework class. /编辑:好的,我没注意到CommandManager是一个框架类。 In this case, you obviously don't want to do what I've proposed. 在这种情况下,你显然不想做我提出的建议。 Jon's solution is to the point: You've got to keep track of your own event and invoke that (eg as a delegate). Jon的解决方案就是要点:你必须跟踪自己的事件并调用它(例如作为代表)。 In keeping with Jon's example, invocation would look like this: 与Jon的例子一致,调用看起来像这样:

canExecuteChanged(sender, EventArgs.Empty);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM