【发布时间】:2023-03-31 02:32:01
【问题描述】:
我正在尝试创建一个 Windows Metro 应用程序。但目前我无法更进一步,因为我需要触发事件或从主页的 settingsflyout 调用方法。但是我在 settingsflyout 中没有主页对象,我不知道如何获得。 有人知道如何做到这一点吗?
【问题讨论】:
标签: c# wpf windows-8 windows-runtime winrt-xaml
我正在尝试创建一个 Windows Metro 应用程序。但目前我无法更进一步,因为我需要触发事件或从主页的 settingsflyout 调用方法。但是我在 settingsflyout 中没有主页对象,我不知道如何获得。 有人知道如何做到这一点吗?
【问题讨论】:
标签: c# wpf windows-8 windows-runtime winrt-xaml
嗯,你应该先了解一些技巧。某些事件,例如按钮的单击事件,无法以编程方式触发。有一些 API 调用,例如 ShowUI(),不能从不是调用堆栈中用户调用事件的结果的事件处理程序调用。不确定这是否有意义,这只是 WinRT 中的一个特殊事物。但是让我们假设您没有尝试调用按钮的单击事件或任何需要用户启动它的 API。
有几种方法可以做你想做的事。这实际上更像是一个 C# 讨论,而不是 Windows 运行时或 XAML 讨论。但是,没关系。这是一个重要的问题。
您遇到此问题是因为浮出控件超出了当前页面的范围。浮出控件不是页面的子页面,它只是由页面调用的东西。浮出控件或页面中的浮出控件中没有对页面的引用。那么我们如何沟通呢?
选项 1
您可以在 app.xaml.cs 中创建一个由浮出控件引发并由页面处理的公共静态事件。由于外部类不能引发其他类的事件,因此您的 app.xaml.cs 还需要一个公共静态方法来触发事件(可以由浮出控件调用)。
有点像
public static event EventHandler MyEvent;
public static void RaiseMyEvent()
{
if (MyEvent != null) MyEvent(null, EventArgs.Empty);
}
这是一个很好的解决方案,因为它可以让浮出控件与调用它的任何页面对话,而无需知道调用它的页面。这意味着两个页面可以调用浮出控件并使用相同的模式对其做出反应。
警告:当您在页面中订阅 app.xaml.cs 事件时,请不要,我重复一遍,当您离开页面时不要忘记取消订阅。请记住,垃圾收集不会从内存中删除任何对另一个具有强引用的对象 - 包括事件处理程序。因此,对于您的 += 逻辑,请务必包含您的 -= 逻辑。 :)
选项 2
如果您没有理由从多个页面调用弹出窗口,您始终可以将静态方法放在页面本身上。浮出控件可以调用此方法并在您的页面上调用某种类型的操作,而无需引用调用它的实例。只要您没有多个页面实例,就可以正常工作。
选项 3
选项 2 的反面是订阅浮出控件上的事件。只要您在页面导航离开时注意取消订阅此事件的警告,就可以这样做。
注意:所有三个选项都可以正常工作。任何告诉您它们是坏主意的人实际上只是在警告您它们是您很容易出错的方法类型。如果是我在这两者之间进行选择,我会选择选项 1。但如果您选择选项 2 或 3,我认为您不会犯错,只是开发人员偏好的选择。请记住退订。
选项 4
高端方法是使用 Microsoft 模式和实践中的 PubSubEvents 等消息传递服务。我在模块(07) Prism - Part 2 中对此进行了详细描述。 MVVM Light 中还有一个消息服务,可以很好地使用。这些是事件聚合器,它们以抽象的方式完成我在选项 1 中描述的内容。这并不优越。但它是可重复的,不太可能通过强参考来实现。如果您觉得这听起来很有趣,那么您可以使用消息服务来完成您在问题中描述的任务。
在此处查找模块 7:http://blog.jerrynixon.com/2014/10/ready-to-learn-developing-universal.html
选项 5+
当然还有其他方法。您可以在弹出的构造函数中传递您的页面的引用 - 尽管这很容易出错和误用,但我不推荐它。您可以使用 VisualTreeHelper 深入了解 CoreWindow 的根元素以查找页面并通过反射调用某些内容。同样,在技术上是可行的,但不推荐,因为它是一堆乱七八糟的代码,很容易出错。
在您的情况下,大多数 XAML 开发人员只使用静态事件。有些人因消息而生死。我只是喜欢做有效的事情。所有这些选项都有效,包括反射疯狂。最终,选择权在您作为开发人员。只有您知道您的应用程序的详细信息。我希望这有帮助。
祝你好运!
【讨论】: