Передача аргументов события оригинального обработчика в Routed Event в wpf - PullRequest
4 голосов
/ 21 декабря 2010

Следующий код показывает нормальное событие и перенаправленное событие. Здесь я использовал то же имя события для объяснения целей, но в действительности я использую только перенаправленное событие.

//Normal Event
public event SelectedHandler Selected;
public delegate void SelectedHandler(Object Sender, RoutedEventArgs e);

//Routed Event
public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent(
"Selected", RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MyUserControl));

//add remove handlers
public event RoutedEventHandler Selected
{
    add { AddHandler(SelectedEvent, value); }
    remove { RemoveHandler(SelectedEvent, value); }
}

Я вызываю эти события из пары обработчиков событий следующим образом

private void lstvMyView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    //Normal Event Raise
    if (Selected != null)
        Selected(this, e);

    //Routed Event Raise
    RoutedEventArgs args = new RoutedEventArgs(SelectedEvent);
    RaiseEvent(args);
}

private void lstvMyView_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    //Normal Event Raise
    if (Selected != null)
        Selected(this, e);

    //Routed Event Raise
    RoutedEventArgs args = new RoutedEventArgs(SelectedEvent);
    RaiseEvent(args);
}

Когда я обрабатываю обычное событие, я могу отправить аргументы обоих обработчиков на событие, но в маршрутизированном событии аргументы будут новым экземпляром. Я хочу передать аргументы обоих обработчиков в Routed Event. Возможно ли этого добиться? Если да, то как?

Ответы [ 2 ]

11 голосов
/ 21 декабря 2010

Прежде всего вам это не нужно (и вы должны удалить его):

//Normal Event
public event SelectedHandler Selected;
public delegate void SelectedHandler(Object Sender, RoutedEventArgs e);

т.е. вам не нужно определять отдельное "нормальное" событие, потому что вы уже сделали это с помощью этого объявления:

public event RoutedEventHandler Selected
{
    add { AddHandler(SelectedEvent, value); }
    remove { RemoveHandler(SelectedEvent, value); }
}

с помощью вышеуказанного блока кода вы «оборачиваете» перенаправленное событие «нормальным» (clr), чтобы пользователи вашего класса могли использовать его с «нормальным» синтаксисом (т. Е. instanceOfMyUserControl.Selected += ....)

секунда, если вы хотите, чтобы аргументы вашего перенаправленного события были такими же, как и аргументы SelectionChanged события ListView, которое вы слушаете, вы должны объявить перенаправленныйсобытие таким образом:

public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent(
"Selected", RoutingStrategy.Bubble,
typeof(SelectionChangedEventHandler),
typeof(MyUserControl));

//add remove handlers
public event SelectionChangedEventHandler Selected
{
    add { AddHandler(SelectedEvent, value); }
    remove { RemoveHandler(SelectedEvent, value); }
}

Обратите внимание, что я заменил RoutedEventHandler на SelectionChangedEventHandler, так как это предопределенный, который может "нести" SelectionChangedEventArgs.

Теперь дляповышение события.Вам не нужно поднимать «нормальный» и маршрутизируемый (так как «нормальный» является оберткой для маршрутизируемого), поэтому вы должны удалить это:

//Normal Event Raise
if (Selected != null)
    Selected(this, e);

и повысить только маршрутизируемую версию, что можно сделать следующим образом:

SelectionChangedEventArgs args = 
    new SelectionChangedEventArgs(SelectedEvent, e.RemovedItems, e.AddedItems);

RaiseEvent(args);

Обратите внимание, что я использую аргументы события из исходного события, чтобы установить AddedItems и RemovedItems одного пользовательского.

0 голосов
/ 22 декабря 2010

Чтобы подписаться на ваш последний комментарий (можно ли дать ссылку на конкретный комментарий?), Я напишу другой ответ, чтобы люди могли следить.

Я думаю, что вы вообще упускаете смысл событий. Что вы хотите, чтобы обработчик вашего события знал, когда он его получает? Как правило, это и есть цель аргументов события - вы передаете некоторую информацию обработчику, с помощью которого вы даете некоторое представление о том, что именно произошло.

Итак, когда вы впервые поднимаете событие, вы сделаете это так:

private void lstvMyView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    SelectionChangedEventArgs args = 
        new SelectionChangedEventArgs(SelectedEvent, e.RemovedItems, e.AddedItems);

    RaiseEvent(args);
}

Сначала вы должны создать аргументы, а затем использовать функцию RaiseEvent() с этими аргументами, потому что вы хотите вызвать специальный маршрутизируемый тип wpf-события. Аргументы должны быть экземпляром класса, который наследует RoutedEventArgs. Обратите внимание, что вы создаете SelectionChangedEventArgs, которые определены в wpf для «переноса» дополнительной информации в обработчик события, а именно, какие элементы были удалены из выбора и какие были добавлены, поэтому, когда обработчик получает событие, он может используйте эту информацию, если он хочет. Об этом думаете, что вы делаете:

//Normal Event Raise
if (Selected != null)
    Selected(this, e);

в основном - (как я сказал в моем первом ответе) удалите его, он вам не нужен.

Итак, что вас беспокоит, так это то, что вы второй раз поднимаете событие. Это прототип того, что вы должны сделать:

private void lstvMyView_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    SelectionChangedEventArgs args = 
        new SelectionChangedEventArgs(SelectedEvent, ?, ?);

    RaiseEvent(args);
}

Как вы видите, вам снова нужно создать SelectionChangedEventArgs и использовать функцию RaiseEvent(), чтобы вызвать событие. Но на этот раз вы не можете использовать e.RemovedItems и e.AddedItems, потому что вы обрабатываете событие MouseLeftButtonUp, которое (через его аргументы) несет информацию о состоянии мыши, а не о том, какие элементы были добавлены в выделение (в конце концов, это событие мыши, а не событие выбора). Вы должны решить, чем заменить два вопросительных знака - как я уже сказал в комментариях к первому ответу, вы должны решить, какую информацию вы хотите донести до пользователя вашего мероприятия. Что означает, что кнопка мыши больше не нажата на «lstvMyView»? Самое простое, что можно сделать, это:

SelectionChangedEventArgs args = 
    new SelectionChangedEventArgs(SelectedEvent, Enumerable.Empty<object>(), Enumerable.Empty<object>());

RaiseEvent(args);

, с помощью которого вы вызываете событие и сообщаете его потребителю, что из выбора не было удалено ни одного элемента и не было добавлено ни одного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...