如何处理在不同页面上发生的事件

时间:2017-05-26 06:52:08

标签: c# xaml uwp

到目前为止,我有一个 UWP 项目有2页。 MainPage.xaml是应用程序的基本布局(汉堡菜单,搜索栏等)。此MainPage的另一部分包含加载另一页LandingPage.xaml的框架。我想从MainPage.xaml中的AutosuggestBox捕获用户输入,并在LandingPage.xaml上显示结果(它位于MainPage.xaml中的一个框架中)。

我尝试继承MainPage,但不允许这样做。

3 个答案:

答案 0 :(得分:3)

虽然玛丽安的回答肯定有效,但我认为它远非“干净”。或者“好”'代码。

首先,您应该在UW​​P应用程序中实现MVVM模式(如果您还没有这样做)并使用依赖注入框架。一个非常基本的,易于理解的是MVVMLight,而更复杂的选择框架可能是Autofac。我建议你从前者开始,先把它包起来要快得多。

在MVVM中,有一个概念可以解决你的问题:信使。我不想在这里详细介绍细节,因为已经有很多非常好的资源来写这个由比我更聪明的人写的。例如,来自MVVMLight本人的作者的这篇文章:https://msdn.microsoft.com/en-us/magazine/jj694937.aspx(我从2013年开始就知道它并谈论Windows 8,但不要担心,概念也是一样的。)

这个想法是,不同的ViewModel不应该彼此之间有严格的依赖关系 - 它使得单元测试(这是首先做MVVM的要点之一)很难。所以在你的情况下,你应该有两个ViewModel:MainViewModel和LandingViewModel。一个用于MainPage,一个用于LandingPage。现在,您应该在MainPage的AutoSuggestBox的QuerySubmitted事件的代码隐藏中实现一个处理程序,并在MainViewModel中调用一个函数。在该函数中,您将使用来自AutoSuggestBox的字符串实例化一个新消息(您可以通过数据绑定到它或通过QuerySubmitted的事件处理程序获取它,它取决于您)并通过传信人。在LandingViewModel中,您可以订阅这个确切的消息,然后它只需几行就可以通过LandingPage上的数据绑定显示收到的消息。

我知道对于像这样非常基本的事情来说,这看起来很麻烦,特别是如果你将它与玛丽安的直接解决方案进行比较。但请相信我,从长远来看编写干净的代码,很好地分离,容易单元测试的ViewModels将弥补你最初需要付出的额外努力才能让它们工作。在两个ViewModel之间建立这样的系统之后,添加第三个(我认为你很快就需要做)这个系统绝对是微不足道的,可以很快完成。

答案 1 :(得分:2)

如果您不使用MVVM,我建议在x:FieldModifier="public"上添加AutoSuggestBox,并向MainPage添加公共静态属性以存储其实例。

<强> MainPage.xaml.cs中

public static MainPage Current { get; private set; }

public MainPage()
{
    Current = this;
    // Rest of your code in ctor
}

然后您可以使用

访问它
string text = MainPage.Current.NameOfYourAutoSuggestBox.Text;

答案 2 :(得分:0)

只需使用您自己的简单消息传递机制,如下所示:

public class Messages {
  public static Messages Instance { get; } = new Messages();

  private readonly List<Subscription> subscriptions;

  private Messages() {
    subscriptions = new List<Subscription>();
  }

  public void Send<T>(T message) {
    var msgType = message.GetType();
    foreach (var sub in subscriptions)
      if (sub.Type.IsAssignableFrom(msgType))
        sub.Handle(message);
  }

  public Guid Subscribe<T>(Action<T> action) {
    var key = Guid.NewGuid();
    lock (subscriptions) {
      subscriptions.Add(new Subscription(typeof(T), key, action));
    }
    return key;
  }

  public void Unsubscribe(Guid key) {
    lock (subscriptions) {
      subscriptions.RemoveAll(sub => sub.Key == key);
    }
  }

  public bool IsSubscribed(Guid key) {
    lock (subscriptions) {
      return subscriptions.Any(sub => sub.Key == key);
    }
  }

  public void Dispose() {
    subscriptions.Clear();
  }
}

internal sealed class Subscription {
  internal Guid Key { get; }
  internal Type Type { get; }
  private object Handler { get; }

  internal Subscription(Type type, Guid key, object handler) {
    Type = type;
    Key = key;
    Handler = handler;
  }

  internal void Handle<T>(T message) {
    ((Action<T>)Handler).Invoke(message);
  }
}

它既小又简单,但是它允许并行订阅不同的消息,并按消息类型分开。在与您类似的情况下,您可以通过以下方式订阅:

Messages.Instance.Subscribe<TextChangeArgs>(OnTextChanged);

和您的其他页面可以使用以下方式发送消息:

Messages.Instance.Send(new TextChangeArgs(...));

只有所有对此特定消息类型感兴趣的用户才能收到该消息。您可以(当然应该)也退订。在现实世界中,还可能需要更多错误处理。

如有必要,您可以添加其他功能,例如轻松进行节流(以避免在给定的时间段内出现太多连续的消息)。