Запустите событие, которое имеет аксессоры - PullRequest
5 голосов
/ 16 октября 2008

Как я могу запустить событие, которое имеет такие методы доступа:

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

Если бы это было обычное событие, я бы запустил его:

CanExecuteChanged(sender, EventArgs..). 

Но здесь это не работает - я могу сделать только

CanExecuteChanged +=..

чтобы прикрепить метод сделать событие - но я не могу его запустить.

Также приветствуется некоторая документация по этому вопросу. Спасибо.

EDIT Это событие из класса, реализующего ICommand в WPF. больше нечего показать :). И нет - CommandManager.RequerySuggested (this, EventArgs.Empty); не работает.

EDIT2 Не уверен, что сказать - пример Джона должен был сработать, даже если метод add был вызван правильно - когда я пытаюсь вызвать событие - это null: |. Я наверное буду отбрасывать события с помощью аксессоров.

Ответы [ 5 ]

4 голосов
/ 16 октября 2008

Я думаю, что вы путали события с делегатами. Только класс, выставляющий событие, может поднять его ... Другие могут только подписаться-отписаться на него. Если вы вызываете событие из класса, объявляющего событие, оно должно работать как обычный делегат.

Лучшая страница, которую я смог найти на События против делегатов . Читать вверх ..

Можете ли вы опубликовать большой фрагмент кода?

Обновление убийцы

Мне кажется, я наконец-то вижу вашу проблему и способы ее решения. Краткий ответ: Он не знает имя делегата, который нужно вызвать, если вы пишете свои собственные методы доступа. Если вы не .. компилятор добавляет приватный делегат с известным именем и, следовательно, может вызвать его

Этот фрагмент кода показывает, что я имею в виду. Эта статья MSDN показала мне свет . Отличный вопрос, чувак .. Я потерял 30 минут. 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!");
        }
}
3 голосов
/ 16 октября 2008

Это событие просто подписывается на другое событие и отписывается от него. Если вы хотите, чтобы ваши подписчики (и только ваши подписчики - не отделялись от других событий) были вызваны, вам нужно будет держать своих подписчиков отдельно. Например, вы можете изменить код на что-то вроде:

private EventHandler canExecuteChanged;

public event EventHandler CanExecuteChanged
{
    add
    {
        CommandManager.RequerySuggested += value;
        canExecuteChanged += value;
    }
    remove
    {
        CommandManager.RequerySuggested -= value;
        canExecuteChanged -= value;
    }
}
1 голос
/ 16 октября 2008

Хорошо, я обнаружил, что если я хочу вызвать это событие, вы должны сделать:

CommandManager.InvalidateRequerySuggested();.
0 голосов
/ 29 ноября 2012

вау, просто были похожие проблемы. Ответ, который помог мне понять, похож на Гишу .

Также из спецификаций 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, и спецификации были самыми последними, я думаю)
0 голосов
/ 16 октября 2008

Вы должны вызывать основные события напрямую. В вашем случае это выглядит так:

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

/ РЕДАКТИРОВАТЬ: Хорошо, я не заметил, что CommandManager это каркасный класс. В этом случае вы явно не хотите делать то, что я предложил. Решение Джона заключается в следующем: вы должны отслеживать свое собственное событие и вызывать его (например, как делегат). В соответствии с примером Джона, вызов будет выглядеть так:

canExecuteChanged(sender, EventArgs.Empty);
...