с использованием прикрепленных событий с калибровочным микро-сообщением. - PullRequest
13 голосов
/ 06 декабря 2011

Я пытаюсь использовать калибровочное микро-сообщение, чтобы вызвать прикрепленное событие, которое я создал:

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?

Ответы [ 3 ]

12 голосов
/ 12 декабря 2011

наконец я понимаю проблему и решение.Проблема в том, что 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; }
}

, а затем, когда вы хотите использовать калибровочное действие:

<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>
0 голосов
/ 05 октября 2017

Вы пробовали это?

cal:Message.Attach="[Event Changing] = [Action SelectedDataChanged($eventArgs)]"

Мне нужно было отправить событие из дочернего элемента управления родителям ViewModel, и оно работало нормально для меня.Я опубликую пример кода, может быть, он кому-нибудь поможет!

Дочерний контроль codebehind:

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]" />
0 голосов
/ 07 декабря 2011

Я не думаю, что синтаксический анализатор для сокращенного синтаксиса 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>
...