代码之家  ›  专栏  ›  技术社区  ›  sirrocco

启动具有访问器的事件

  •  5
  • sirrocco  · 技术社区  · 17 年前

    如何启动具有如下访问器的事件:

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

    如果这是正常事件,我会通过以下方式启动它:

    CanExecuteChanged(sender, EventArgs..). 
    

    但在这里它不起作用-我只能这样做

    CanExecuteChanged +=..
    

    附加一个方法来执行事件-但我无法启动它。

    此外,我们还将感谢有关这一主题的一些文件。 谢谢。

    编辑 事件来自在WPF中实现ICommand的类。没什么可展示的了:)。 不-commandmanager.requerySuggested(this,eventargs.empty);不起作用。

    编辑2 不知道该说什么-即使正确调用了add方法,jon的示例也应该有效-当我尝试调用事件时-它为空:。我可能会的 使用访问器删除事件。

    5 回复  |  直到 13 年前
        1
  •  3
  •   Jon Skeet    17 年前

    该事件只是订阅和取消订阅另一个事件。如果你想要你的订户(和 只有 您的订阅者-而不是将其与其他事件分开)要被调用,您需要单独保留订阅者。例如,您可以将代码更改为:

    private EventHandler canExecuteChanged;
    
    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
            canExecuteChanged += value;
        }
        remove
        {
            CommandManager.RequerySuggested -= value;
            canExecuteChanged -= value;
        }
    }
    
        2
  •  4
  •   Gishu    17 年前

    我认为你的事件与代表们混淆了。只有公开事件的类才能引发它…其他人只能订阅取消订阅。如果从声明事件的类中调用事件,那么它应该像常规委托一样工作。

    我能找到的最好的页面 Events vs Delegates . 读起来。

    你能贴一个更大的片段吗?好像出了点问题……

    杀手更新

    我想我终于看到了你的问题和解决方法。 简短回答: 如果编写自己的访问器,它不知道要调用的委托的名称。如果你不知道。编译器添加了已知名称的私有委托,因此能够调用它

    这段代码片段显示了我的意思。这个 MSDN article showed me the light . 好问题,哥们……我输了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!");
            }
    }
    
        3
  •  1
  •   sirrocco    17 年前

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

    CommandManager.InvalidateRequerySuggested();.
    
        4
  •  0
  •   Konrad Rudolph    17 年前

    您必须直接调用底层事件。在您的案例中,这看起来像是:

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

    /编辑:好吧,我没注意到 CommandManager 是框架类。在这种情况下,你显然不想按我的建议去做。乔恩的解决方案是:你必须跟踪你自己的事件并调用它(例如作为一个委托人)。与jon的示例一致,调用如下所示:

    canExecuteChanged(sender, EventArgs.Empty);
    
        5
  •  0
  •   sss    13 年前

    哇,也有类似的问题。帮助我理解的答案有点像 Gishu .

    同样来自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();
            }
        }
    }
    

    这里演示了两种事件

    1. 类字段事件=>我们可以调用
    2. 带有访问器的事件=>我们无法调用(在规范中找不到这一点,原因可能是我错过了它)(我猜,它只是在Visual Studio 2005上测试的,而且规范是最新的)
    推荐文章