Используя приложенные события с калибром micro Message.Attach
Я пытаюсь использовать микроволновое сообщение caliburn для запуска присоединенного события, которое я создал:
public static class DataChanging
{
public delegate void DataChangingEventHandler(object sender, DataChangingEventArgs e);
public static readonly RoutedEvent ChangingEvent =
EventManager.RegisterRoutedEvent("Changing",
RoutingStrategy.Bubble,
typeof(DataChangingEventHandler),
typeof(DataChanging));
public static void AddChangingHandler(DependencyObject o, DataChangingEventHandler handler)
{
((UIElement)o).AddHandler(DataChanging.ChangingEvent, handler);
}
public static void RemoveChangingHandler(DependencyObject o, DataChangingEventHandler handler)
{
((UIElement)o).RemoveHandler(DataChanging.ChangingEvent, handler);
}
public static bool GetActivationMode(DependencyObject obj)
{
return (bool)obj.GetValue(ActivationModeProperty);
}
public static void SetActivationMode(DependencyObject obj, bool value)
{
obj.SetValue(ActivationModeProperty, value);
}
public static readonly DependencyProperty ActivationModeProperty =
DependencyProperty.RegisterAttached("ActivationMode",
typeof(bool),
typeof(DataChanging),
new FrameworkPropertyMetadata(false,
HandleActivationModeChanged));
private static void HandleActivationModeChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var dataGrid = target as XamDataGrid;
if (dataGrid == null) // if trying to attach to something else than a datagrid, just ignore
return;
if ((bool)e.NewValue)
{
dataGrid.RecordDeactivating += selector_RecordDeactivating;
}
else
{
dataGrid.RecordDeactivating -= selector_RecordDeactivating;
}
}
static void selector_RecordDeactivating(object sender, RecordDeactivatingEventArgs e)
{
var args = new DataChangingEventArgs(DataChanging.ChangingEvent,sender)
{
Data = ((DataRecord) e.Record).DataItem,
ShouldCancelChange = false
};
(sender as UIElement).RaiseEvent(args);
e.Cancel = args.ShouldCancelChange;
}
}
В самой XAML я добавил следующую строку:
cal:Message.Attach="[Helpers:DataChanging.Changing] = [Action SelectedDataChanged($eventArgs)]"
Помощники ссылаются на правильное пространство имен.
Я также пробовал другие версии, которые не выполнялись (полное пространство имен):
cal:Message.Attach="[clr-namespace:RTF.Client.UI.Helpers.DataChanging.Changing] = [Action SelectedDataChanged($eventArgs)]"
попытался самостоятельно установить событие взаимодействия:
Когда я пытался добавить обычный триггер событий, все работало хорошо, поэтому это не мое вложенное объявление события:
<EventTrigger RoutedEvent="Helpers:DataChanging.Changing">
<EventTrigger.Actions>
<BeginStoryboard x:Name="sb">
<Storyboard x:Name="dsf">
<Storyboard x:Name="myStoryboard">
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="SSS" Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
Что я здесь делаю неправильно?
Невозможно присоединить присоединенное событие и вызвать его с помощью микросхемы caliburn micro?
Ответы
Ответ 1
Наконец, я понимаю проблему и решение.
Проблема в том, что system.windows.interactiviy.EventTrigger не поддерживает прикрепленные события.
Caliburn micro использует его для действий, поэтому мое прикрепленное событие не сработало.
Решение заключалось в том, чтобы написать настраиваемый триггер события и использовать калибровочное микро-действие в явном виде.
из этого сообщения был взят настраиваемый триггер событий: http://joyfulwpf.blogspot.com/2009/05/mvvm-invoking-command-on-attached-event.html?showComment=1323674885597#c8041424175408473805
public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
RoutedEvent _routedEvent;
public RoutedEvent RoutedEvent
{
get { return _routedEvent; }
set { _routedEvent = value; }
}
public RoutedEventTrigger() { }
protected override void OnAttached()
{
Behavior behavior = base.AssociatedObject as Behavior;
FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement;
if (behavior != null)
{
associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
}
if (associatedElement == null)
{
throw new ArgumentException("Routed Event trigger can only be associated to framework elements");
}
if (RoutedEvent != null)
{ associatedElement.AddHandler(RoutedEvent, new RoutedEventHandler(this.OnRoutedEvent)); }
}
void OnRoutedEvent(object sender, RoutedEventArgs args)
{
base.OnEvent(args);
}
protected override string GetEventName() { return RoutedEvent.Name; }
}
а затем, когда вы хотите использовать действие caliburn:
<i:Interaction.Triggers>
<!--in the routed event property you need to put the full name space and event name-->
<Helpers:RoutedEventTrigger RoutedEvent="Helpers:DataChanging.Changing">
<cal:ActionMessage MethodName="SelectedDataChanged">
<cal:Parameter Value="$eventargs" />
</cal:ActionMessage>
</Helpers:RoutedEventTrigger>
</i:Interaction.Triggers>
Ответ 2
Я не думаю, что синтаксический анализатор синтаксиса Message.Attach поддерживает прикрепленные события. Но почему бы вам просто не добавить ActionMessage непосредственно в действия EventTrigger?
<EventTrigger RoutedEvent="Helpers:DataChanging.Changing">
<EventTrigger.Actions>
<!-- new part -->
<cal:ActionMessage MethodName="SelectedDataChanged">
<cal:Parameter Value="$eventargs" />
</cal:ActionMessage>
<!-- /new part -->
<BeginStoryboard x:Name="sb">
<Storyboard x:Name="dsf">
<Storyboard x:Name="myStoryboard">
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="SSS" Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
Ответ 3
Вы пробовали это?
cal:Message.Attach="[Event Changing] = [Action SelectedDataChanged($eventArgs)]"
Мне нужно было отправить событие из дочернего элемента управления в родительский ViewModel, и это сработало для меня. Я отправлю пример кода, возможно, это поможет кому-то!
Код детского контроля:
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
#region Routed Events
public static readonly RoutedEvent ControlClosedEvent = EventManager.RegisterRoutedEvent(
"ControlClosed",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MyControl));
public event RoutedEventHandler ControlClosed
{
add { AddHandler(ControlClosedEvent, value); }
remove { RemoveHandler(ControlClosedEvent, value); }
}
#endregion Routed Events
private void Close(object sender, RoutedEventArgs e)
{
var rea = new RoutedEventArgs(ControlClosedEvent);
RaiseEvent(rea);
}
}
Управление детьми XAML:
<Button Grid.Row="1" Grid.Column="0"
Content="Close Me!" Height="50"
Click="Close" />
Родительский вид:
<userControls:MyControl cal:Message.Attach="[Event ControlClosed] = [Action ClosePopup]" />