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不知道该说什么 - 即使正确调用了 add 方法,Jon 的示例也应该有效 - 当我尝试调用事件时 - 它是 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

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

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

您必须直接调用底层事件。在您的情况下,看起来好像是:

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

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

canExecuteChanged(sender, EventArgs.Empty);
于 2008-10-16T11:08:47.383 回答
0

哇,刚刚遇到类似的问题。帮助我理解的答案有点像Gishu 的

同样来自 C# 规范,http://www.microsoft.com/en-us/download/details.aspx?id= 7029,在“10.8.1 Field-like events”下,它说“在编译类似 field 的事件时,编译器会自动创建存储来保存委托,”

规格还说:

因此,以下形式的实例事件声明:

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. 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)
于 2012-11-29T02:25:53.463 回答