【问题标题】:Attached Events附加事件
【发布时间】:2016-05-24 23:42:50
【问题描述】:

我想将一个点击事件附加到我的容器中,但是 c++/cx 的方式让我无法理解。 XAML 和编程方法都让我感到沮丧。我一般如何附加事件? (特别是 Button 的 Click 事件?)以下两种方法都不适合我:

<StackPanel x:Name="stackPanel" Button.Click="stackPanel_Click">
    <Button>Button #1</Button>
    <Button>Button #2</Button>    
</StackPanel>

这只是给出了错误,“未知的可附加成员 'Button.Click' 在元素 'StackPanel' 上。然而,这就是它在 WPF 中的完成方式。并且以编程方式:

stackPanel->AddHandler(
  Windows::UI::Xaml::Controls::Button::Click,
  ref new Windows::UI::Xaml::RoutedEventHandler(this, stackPanel_Click),
  false);

这给出了“错误:非静态成员引用必须相对于特定对象”——它指的是 AddHandler 的第一个参数。

我基本上理解给出的错误,但仍然不知道如何完成我想要的。搜索引擎没有提供任何帮助,微软的文档也没有启发。

【问题讨论】:

  • 这就是我需要将事件附加到它的原因。当 Button(s) Click 事件触发时,它将冒泡到 StackPanel - 此代码在 C# WPF 中运行良好,但不适用于 c++/cx 中的 UWP 应用程序。

标签: xaml c++-cx


【解决方案1】:

经过一番思考和更多研究,我发现了解决方案。

XAML

<StackPanel x:Name="stackPanel" UIElement.Tapped="stackPanel_Tapped">
  <Button>Button #1</Button>
  <Button>Button #2</Button>
</StackPanel>

在代码中

// For in-code-only setup, consider this constructor and
// OnLoaded code.
MyPage::MyPage() {
  InitializeComponent();

  Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &MyPage::OnLoaded);
}

void MyPage::OnLoaded(Platform::Object^ sender, RoutedEventArgs^ e) {
  stackPanel->AddHandler(
    UIElement::TappedEvent,
    ref new TappedEventHandler(this, &MyPage::stackPanel_Tapped),
    false);
}

// If you setup the event handling in XAML this is the only code you'll need.
void MyPage::stackPanel_Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e) {
  // Event handling code . . .
}

第一个示例代码不起作用的原因是似乎没有任何对 RoutedEvent 对象的引用来进行单击,按惯例将其命名为 ClickEvent。尽管如此,文档仍然说 Button::Click 是一个路由事件。该平台似乎倾向于更高级别的抽象,而是定义了一个名为 Tapped 的路由事件。毕竟,UWP 应用程序可以在许多不同的设备上运行,但并非所有设备都有鼠标或光标。 click 和 tapped 这两个事件都可以使用,但只有 tapped 可以用作附加事件——它似乎是我们唯一可以访问路由事件的 RoutedEvent 对象的事件。

第二个值得注意且非常相关的点是代码内实现。您传入名为 TappedEvent 的 RoutedEvent 对象,而不是名为 Tapped 的事件。我之所以提到它,是因为 XAML 代码可能会诱使您只输入 Tapped 而不是 TappedEvent,这可能会让您有些摸不着头脑,即使您在智能感知中查看 AddHandler 函数原型也是如此。

【讨论】:

  • Click UWP XAML 中的事件不会通过树进行路由。您当然可以将Click 处理程序添加到按钮本身。此外,您应该在引发 Loaded 事件后立即取消挂钩,因为它可能在未来再次引发,并且您将拥有两个 Tapped 处理程序。
  • @PeterTorr-MSFT 感谢您指出加载事件的潜在问题。据我了解,在离开页面时,页面对象是序列化的。然后,如果您碰巧“返回”到该页面,则会创建另一个实例并且该对象被“重新水化”。你想到的情况是这样的吗?还是有另一种情况调用了Loaded,但是原来的对象没有被销毁?那部分代码模仿了微软网站上的代码,所以我把它包括在内。 (在 UWP 页面上似乎没有 KeepAlive 属性可以做到这一点。)
  • 导航可以根据不同情况回收页面。通常,如果页面(或其任何父级)被删除并重新添加到树中,例如作为某些转换或响应式设计的一部分,您可能会收到另一个 Loaded 事件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2011-10-11
  • 2014-09-08
相关资源
最近更新 更多