2

假设我正在为 Windows Phone 应用程序(Silverlight)制作程序集(WindowsPhoneClassLibrary 或 PortableClassLibrary)。

有没有办法让我自动检测/注册/订阅Application.Current.RootVisual不为空的那一刻?

我目前(由于异常而无法工作)的方法是:

var rootVisualTask = new TaskCompletionSource<UIElement>();
var application = Application.Current;
TaskEx.Run(() =>
{
    while (application.RootVisual == null)
        Thread.Sleep(1);
    rootVisualTask.TrySetResult(application.RootVisual);
});
var rootVisual = await rootVisualTask.Task;

编辑

回答 McGarnagle 解释我的程序集通常是如何初始化的。

在 App.xaml.cs 中:

static readonly PhoneApplicationFrame RootFrame = new PhoneApplicationFrame();
public App()
{
    InitializeComponent();
    RootFrame.Navigated += RootFrame_Navigated;
}
void RootFrame_Navigated(object sender, NavigationEventArgs e)
{
    RootVisual = RootFrame;
    RootFrame.Navigated -= RootFrame_Navigated;
}
void Application_Launching(object sender, LaunchingEventArgs e)
{
    MyPlugin.Start();
}
void Application_Activated(object sender, ActivatedEventArgs e)
{
    MyPlugin.Start();
}

事情按以下顺序发生:

  1. Application.Startup(没用过)
  2. Application.Launching(插件启动)
  3. RootFrame.Navigated(设置了 RootVisual,但 RootFrame 是私有的)

我可能需要MyPlugin.HeyRootVisualIsSetAndNowYouCanUseIt()手动插入,RootVisual = ...但我试图避免这种情况。

编辑

与 Obj-C 不同,KVO 不能在您不拥有的 Fields/Properties 上实现。这意味着可能没有人会找到更好的解决方案。

4

1 回答 1

0

经过几个小时的试验,我发现这个工作:

var dispatcher = Deployment.Current.Dispatcher;
var application = Application.Current;
UIElement rootVisual = null;
while (rootVisual == null)
{
    var taskCompletionSource = new TaskCompletionSource<UIElement>();
    dispatcher.BeginInvoke(() =>
        taskCompletionSource.TrySetResult(application.RootVisual));
    rootVisual = await taskCompletionSource.Task;
}

我的问题的Thread.Sleep(1);from 循环被调用替换Deployment.Current.Dispatcher.BeginInvoke()为避免抛出异常。

于 2014-07-11T09:22:12.617 回答