【问题标题】:Caliburn.Micro attach event handler on event of BehaviorCaliburn.Micro 在行为事件上附加事件处理程序
【发布时间】:2015-06-13 18:33:33
【问题描述】:

我编写了自己的 Behavior 来处理滑动手势并将其放入 ListView 的 ItemTemplate。如果完成滑动,我会为 LeftSwipe 或 RightSwipe 引发事件。这个事件应该由我的 ViewModel 处理。

我使用 Caliburn.Micro 的语法将处理程序附加到事件:cm:Message.Attach="[Event LeftSwipe] = [LeftSwipe($source, $eventArgs)"

这是我的行为:

public class SwipeInteractionBehavior : DependencyObject, IBehavior
{
    public DependencyObject AssociatedObject { get; private set; }

    public void Attach(DependencyObject associatedObject)
    {
        // ...
    }

    public void Detach()
    {
        // ...
    }

    public event EventHandler LeftSwipe;

    public event EventHandler RightSwipe;

    // ...
    // ...

    private void OnLeftSwipe(FrameworkElement element)
    {
        // ...

        if (LeftSwipe != null)
        {
            LeftSwipe(this, EventArgs.Empty);
        }
    }

    private void OnRightSwipe(FrameworkElement element)
    {
        // ...
        if (RightSwipe != null)
        {
            RightSwipe(this, EventArgs.Empty);
        }

    }
}

这就是我在 ListViews ItemTemplate 中使用此行为的方式:

        <ListView x:Name="Links" IsItemClickEnabled="True" SelectionMode="None" cm:Message.Attach="[Event ItemClick] = [Click($source, $eventArgs)]">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid>
                            <Border x:Name="todoItem" Loaded="Border_Loaded" Background="White">
                                <i:Interaction.Behaviors>
                                    <local:SwipeInteractionBehavior cm:Message.Attach="[Event LeftSwipe] = [LeftSwipe($source, $eventArgs)]" />
                                </i:Interaction.Behaviors>

                                <Grid>
                                    <StackPanel>
                                        <TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemContentTextBlockStyle}" />
                                        <TextBlock Text="{Binding Url}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
                                        <TextBlock Text="{Binding Tags, Converter={StaticResource ListToString}}" />
                                    </StackPanel>
                                </Grid>
                            </Border>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

如果我引发 LeftSwipe 事件,我会遇到异常,这是我的 StackTrace:

System.Exception was not handled.
  HResult=-2146233088
  Message=No target found for method LeftSwipe.
  Source=Caliburn.Micro.Platform
  StackTrace:
       at Caliburn.Micro.ActionMessage.Invoke(Object eventArgs)
       at Caliburn.Micro.TriggerAction`1.Execute(Object sender, Object parameter)
       at Microsoft.Xaml.Interactivity.Interaction.ExecuteActions(Object sender, ActionCollection actions, Object parameter)
       at Microsoft.Xaml.Interactions.Core.EventTriggerBehavior.OnEvent(Object sender, Object eventArgs)
       at ReaderApp.SwipeInteractionBehavior.<>c__DisplayClass5.<OnLeftSwipe>b__4()
       at ReaderApp.Extensions.FrameworkElementExtension.<>c__DisplayClass2.<Animate>b__0(Object s, Object e)
  InnerException: 

视图模型:

public class MainViewModel : ViewModelBase
{
    private readonly IEventAggregator eventAggregator;
    private readonly Database database;

    public BindableCollection<Link> Links
    {
        get;
        private set;
    }

    public MainViewModel(INavigationService navigationService, IEventAggregator eventAggregator, Database database)
        : base(navigationService)
    {
        this.eventAggregator = eventAggregator;
        this.database = database;

        Links = new BindableCollection<Link>();
    }

    public async void LeftSwipe(object sender, EventArgs e)
    {
        // ...
    }

    public void RightSwipe(object sender, EventArgs e)
    {
        // ...
    }
}

【问题讨论】:

  • 好像找不到LeftSwipe方法,能否分享一下LinkViewModel(或者ListView绑定的)的视图模型代码
  • 我添加了 ViewModel 代码。如果我将 SwipeInteraction 实现为 ContentControl,它可以正常工作。在 Behaviors 上使用附加属性似乎是不可能的。
  • 我需要研究一下,另一种可能的方法是将 SwipeInteraction 实现为使用 ActionMessage 作为操作的触发器。

标签: c# xaml winrt-xaml caliburn.micro behavior


【解决方案1】:

所以问题是ActionMessage 继承了TriggerAction&lt;FrameworkElement&gt;,这意味着它无法正确附加到SwipeInteractionBehavior

WPF/Silverlight/Windows Phone 8 交互 SDK 和 WinRT 交互 SDK 之间存在一些主要的 API 差异这一事实也使情况变得复杂。您可以在Parser cmets 中看到一些我的意思。

我建议将SwipeInteractionBehavior 实现为触发行为,就像EventTriggerBehavior,这曾经是一个单独的基类,但在WinRT 中它仍然是IBehavior,区别在于它有一个名为 Actions 的属性,类型为 ActionCollection。愚蠢的是,没有接口是执行此操作的基类,因此 Caliburn.Micro 陷入了一些假设。

然后您将使用 Interaction.ExecuteActions 触发这些操作,最终您的 xaml 应该看起来像这样。

<Border x:Name="SwipeTarget">
  <i:Interaction.Behaviors>
    <local:SwipeEventBehavior Direction="Left">
      <cm:ActionMessage AssociatedObject="{Binding ElementName=SwipeTarget" Method="LeftSwipe" />
    </local:SwipeEventBehavior>
  </i:Interaction.Behaviors>
</Border>

这有点冗长,但我们需要解决 SDK 更改带来的限制。

【讨论】:

  • 非常感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
相关资源
最近更新 更多