如何从“设置”弹出窗口在页面上触发事件
How to trigger an event at a page from Settings flyout
我正在尝试创建一个 windows Metro 应用程序。但目前我不能走得更远,因为我需要有可能触发一个事件或从主页的 settingsflyout 调用一个方法。但是我在 settingsflyout 中没有主页对象,我不知道如何获得。
有人知道怎么做吗?
好吧,您应该首先了解一些技巧。某些事件,例如按钮的单击事件,无法以编程方式触发。有一些 API 调用,例如 ShowUI() 不能从事件处理程序调用,这不是调用堆栈中用户调用事件的结果。不确定这是否有意义,这只是 WinRT 中的一个特殊事物。但是让我们假设您没有尝试调用按钮或任何需要用户启动它的 API 的单击事件。
有多种方法可以满足您的需求。这实际上更像是 C# 讨论,而不是 Windows 运行时或 XAML 讨论。但是,没关系。这是一个重要的问题。
您遇到此问题是因为弹出窗口超出了当前页面的范围。浮出控件不是页面的子项,它只是页面调用的东西。没有对弹出窗口中的页面或页面中的弹出窗口的引用。那我们怎么沟通呢?
选项 1
您可以在 app.xaml.cs 中创建一个 public 静态事件,该事件由弹出窗口引发并由页面处理。由于外部 类 无法引发其他 类 的事件,您的 app.xaml.cs 还需要一个 public 静态方法来触发事件(可以由弹出窗口调用)。
有点像这样
public static event EventHandler MyEvent;
public static void RaiseMyEvent()
{
if (MyEvent != null) MyEvent(null, EventArgs.Empty);
}
这是一个很好的解决方案,因为它可以让弹出窗口与调用它的任何页面对话,而无需知道调用它的页面。这意味着两个页面可以调用浮出控件并且都使用相同的模式对其作出反应。
警告:当您订阅页面中的 app.xaml.cs 事件时,我再说一遍,不要忘记在离开页面时取消订阅。请记住,垃圾回收不会从内存中删除任何对另一个对象具有强引用的对象 - 包括事件处理程序。因此,对于您的 +=
逻辑,请务必也包含您的 -=
逻辑。 :)
选项 2
如果您没有理由从多个页面调用浮出控件,您始终可以将静态方法放在页面本身上。浮出控件可以调用此方法并在您的页面上调用某种类型的操作,而无需引用调用它的实例。只要您没有超过一个页面实例,这就可以正常工作。
选项 3
选项 2 的反面是订阅浮出控件上的事件。只要您在页面导航离开时注意取消订阅此事件的警告,就可以这样做。
Note: all three options work just fine. Anyone telling you that they are bad ideas are really just warning you that they are the types of approaches that you can get wrong easily. If it were me picking between then, I would choose option 1. But if you chose option 2 or 3, I would not think you made a mistake, just a developer preference sort of choice. Just remember to unsubscribe.
选项 4
高端方法是使用 Microsoft 模式和实践中的 PubSubEvents 等消息服务。我在模块 (07) Prism - Part 2
中对此进行了详细描述。 MVVM Light 中还有一个消息服务,很好用。这些是事件聚合器,它们以抽象的方式完成我在选项 1 中描述的内容。这并不优越。但它是可重复的,不太可能通过强引用来实现。如果您觉得这听起来很有趣,那么您可以使用消息服务来完成您在问题中描述的任务。
Find module 7 here: http://blog.jerrynixon.com/2014/10/ready-to-learn-developing-universal.html
选项 5+
当然还有其他方法。您可以在弹出窗口的构造函数中传递您的页面的引用 - 虽然这很容易出错和误用,但我不推荐这样做。您可以使用 VisualTreeHelper 探查 CoreWindow 的根元素以查找页面并调用带有反射的内容。同样,技术上可行,但不推荐,因为它是一堆代码,很容易出错。
大多数 XAML 开发人员在您的情况下只使用静态事件。有些人因消息传递而生死存亡。我只是喜欢做有用的事。所有这些选项都有效,包括反射疯狂。最终,选择权在您作为开发人员。只有您知道应用程序的详细信息。我希望这有帮助。
祝你好运!
我正在尝试创建一个 windows Metro 应用程序。但目前我不能走得更远,因为我需要有可能触发一个事件或从主页的 settingsflyout 调用一个方法。但是我在 settingsflyout 中没有主页对象,我不知道如何获得。 有人知道怎么做吗?
好吧,您应该首先了解一些技巧。某些事件,例如按钮的单击事件,无法以编程方式触发。有一些 API 调用,例如 ShowUI() 不能从事件处理程序调用,这不是调用堆栈中用户调用事件的结果。不确定这是否有意义,这只是 WinRT 中的一个特殊事物。但是让我们假设您没有尝试调用按钮或任何需要用户启动它的 API 的单击事件。
有多种方法可以满足您的需求。这实际上更像是 C# 讨论,而不是 Windows 运行时或 XAML 讨论。但是,没关系。这是一个重要的问题。
您遇到此问题是因为弹出窗口超出了当前页面的范围。浮出控件不是页面的子项,它只是页面调用的东西。没有对弹出窗口中的页面或页面中的弹出窗口的引用。那我们怎么沟通呢?
选项 1
您可以在 app.xaml.cs 中创建一个 public 静态事件,该事件由弹出窗口引发并由页面处理。由于外部 类 无法引发其他 类 的事件,您的 app.xaml.cs 还需要一个 public 静态方法来触发事件(可以由弹出窗口调用)。
有点像这样
public static event EventHandler MyEvent;
public static void RaiseMyEvent()
{
if (MyEvent != null) MyEvent(null, EventArgs.Empty);
}
这是一个很好的解决方案,因为它可以让弹出窗口与调用它的任何页面对话,而无需知道调用它的页面。这意味着两个页面可以调用浮出控件并且都使用相同的模式对其作出反应。
警告:当您订阅页面中的 app.xaml.cs 事件时,我再说一遍,不要忘记在离开页面时取消订阅。请记住,垃圾回收不会从内存中删除任何对另一个对象具有强引用的对象 - 包括事件处理程序。因此,对于您的 +=
逻辑,请务必也包含您的 -=
逻辑。 :)
选项 2
如果您没有理由从多个页面调用浮出控件,您始终可以将静态方法放在页面本身上。浮出控件可以调用此方法并在您的页面上调用某种类型的操作,而无需引用调用它的实例。只要您没有超过一个页面实例,这就可以正常工作。
选项 3
选项 2 的反面是订阅浮出控件上的事件。只要您在页面导航离开时注意取消订阅此事件的警告,就可以这样做。
Note: all three options work just fine. Anyone telling you that they are bad ideas are really just warning you that they are the types of approaches that you can get wrong easily. If it were me picking between then, I would choose option 1. But if you chose option 2 or 3, I would not think you made a mistake, just a developer preference sort of choice. Just remember to unsubscribe.
选项 4
高端方法是使用 Microsoft 模式和实践中的 PubSubEvents 等消息服务。我在模块 (07) Prism - Part 2
中对此进行了详细描述。 MVVM Light 中还有一个消息服务,很好用。这些是事件聚合器,它们以抽象的方式完成我在选项 1 中描述的内容。这并不优越。但它是可重复的,不太可能通过强引用来实现。如果您觉得这听起来很有趣,那么您可以使用消息服务来完成您在问题中描述的任务。
Find module 7 here: http://blog.jerrynixon.com/2014/10/ready-to-learn-developing-universal.html
选项 5+
当然还有其他方法。您可以在弹出窗口的构造函数中传递您的页面的引用 - 虽然这很容易出错和误用,但我不推荐这样做。您可以使用 VisualTreeHelper 探查 CoreWindow 的根元素以查找页面并调用带有反射的内容。同样,技术上可行,但不推荐,因为它是一堆代码,很容易出错。
大多数 XAML 开发人员在您的情况下只使用静态事件。有些人因消息传递而生死存亡。我只是喜欢做有用的事。所有这些选项都有效,包括反射疯狂。最终,选择权在您作为开发人员。只有您知道应用程序的详细信息。我希望这有帮助。
祝你好运!