Запустить событие с аксессорами
Вопрос
Как я могу запустить событие с такими аксессорами:
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
Если бы это было обычное событие, я бы запустил его:
CanExecuteChanged(sender, EventArgs..).
Но здесь это не работает - я могу только сделать
CanExecuteChanged +=..
чтобы прикрепить метод, выполните событие, но я не могу его запустить.
Также будет оценена некоторая документация по этому вопросу.Спасибо.
РЕДАКТИРОВАТЬСобытие происходит из класса, реализующего ICommand в WPF.больше нечего показывать :).И нет - CommandManager.RequerySuggested(this, EventArgs.Empty);не работает.
РЕДАКТИРОВАТЬ2 Не знаю, что сказать — пример Джона должен был сработать, даже если метод добавления вызывается правильно — когда я пытаюсь вызвать событие, оно равно нулю :|.Я, наверное, брошу мероприятия с аксессуами.
Решение
Это событие просто подписка на другое событие и отписка от него.Если вы хотите, чтобы ваши подписчики (и только ваши подписчики, а не отдельные для другого события) для вызова, вам нужно будет хранить своих подписчиков отдельно.Например, вы можете изменить код на что-то вроде:
private EventHandler canExecuteChanged;
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
canExecuteChanged += value;
}
remove
{
CommandManager.RequerySuggested -= value;
canExecuteChanged -= value;
}
}
Другие советы
Я думаю, вы путаете события с делегатами.Только класс, раскрывающий событие, может его вызвать...Остальные могут только подписаться-отписаться на него.Если вы вызываете событие из класса, объявляющего событие, оно должно работать как обычный делегат.
Лучшая страница, которую я смог найти на События против делегатов.Прочитать..
Можешь выложить фрагмент побольше..кажется что-то не так..
Убийственное обновление
Кажется, я наконец-то увидел вашу проблему и способы ее решения.Короткий ответ: Он не знает имени делегата, который будет вызываться, если вы пишете свои собственные методы доступа.Если вы этого не сделаете..компилятор добавляет частный делегат с известным именем и, следовательно, может его вызвать
Этот фрагмент кода показывает, что я имею в виду.Этот Статья 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!");
}
}
Хорошо, я обнаружил, что если я хочу вызвать это событие, вам нужно сделать:
CommandManager.InvalidateRequerySuggested();.
Вам нужно напрямую вызывать базовые события.В вашем случае это выглядит так:
<blockquote>CommandManager.RequerySuggested(sender, EventArgs.…)</blockquote>
/РЕДАКТИРОВАТЬ:ок, я этого не заметил CommandManager
это класс фреймворка.В данном случае вы явно не хотите делать то, что я предложил.Решение Джона по существу:Вы должны отслеживать свое собственное событие и вызывать его (например.в качестве делегата).В соответствии с примером Джона вызов будет выглядеть так:
canExecuteChanged(sender, EventArgs.Empty);
вау, только что были похожие проблемы.Ответ, который помог мне понять, примерно такой: Гишу.
Также из спецификаций 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();
}
}
}
Здесь показаны два типа событий.
- Полевые события => мы можем вызывать
- события с аксессорами => мы не можем вызывать (не могу найти это в спецификациях, почему, возможно, я это пропустил) (и тестировал это только в Visual Studio 2005, и, я думаю, спецификации были самыми последними)