【问题标题】:using attached events with caliburn micro Message.Attach使用带有 caliburn 微 Message.Attach 的附加事件
【发布时间】:2011-12-06 15:26:09
【问题描述】:

我正在尝试使用 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 调用它?

【问题讨论】:

    标签: c# xaml caliburn.micro attached-properties routed-events


    【解决方案1】:

    我终于明白了问题和解决方案。 问题是 system.windows.interactiviy.EventTrigger 不支持附加事件。 Caliburn micro 将其用于操作,因此我附加的事件不起作用。 解决方案是编写自定义事件触发器并以显式方式使用 caliburn 微操作。 自定义事件触发器取自该帖子: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 的 Actions 中呢?

      <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>
      

      【讨论】:

      • 我试过了,但 Caliburn 操作消息仅适用于 system.windows 的操作。 interactivity.Event 触发器而不是正常的触发器。老实说,我不确定两者之间有什么区别。我无法使用 system.windows.interactivity.event 触发器开始我的活动。
      【解决方案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]" />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-28
        • 2016-09-17
        • 1970-01-01
        • 2012-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多