简体   繁体   English

UWP C# 将 UI 对象返回到主线程上的同步扩展方法

[英]UWP C# Return UI object to synchronous extension method on main thread

I am trying to write an extension method for the Page class that will return a user control which is a dynamically created child of the root Grid .我正在尝试为Page类编写一个扩展方法,该方法将返回一个用户控件,该控件是根Grid的动态创建的子项。 The issue I am having is working with the Content property of the Page class.我遇到的问题是使用Page类的Content属性。

The aim is to return the control for the purpose of checking the control's properties, and will mostly be called from the main thread.目的是为了检查控件的属性而返回控件,并且主要从主线程调用。

Here is what I'm trying to do:这是我想要做的:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    //throws "marshalled from a different thread" exception
    Grid rootGrid = page.Content as Grid;  

    if(rootGrid != null) {
        var controls = rootGrid.Children.OfType<MyUserControl>();

        foreach(MyUserControl control in controls)
        {
            if(control.Tag == tag) return control;
        }

    return null;
}

I have tried making a helper method of return type Task<Grid> to get the object, but I can't find a way to synchronously return the asynchronous Task, and I can't seem to find a way to synchronously return a value from page.Dispatcher.RunAsync() .我尝试创建一个返回类型Task<Grid>的辅助方法来获取对象,但是我找不到同步返回异步任务的方法,而且我似乎找不到同步返回值的方法page.Dispatcher.RunAsync()

This is generally what the XAML layout looks like:这通常是 XAML 布局的样子:

<Page>
    <Grid>
        ...
        ...
        ...
        <MyUserControl/>
        <MyUserControl/>
        <MyUserControl/>
    <Grid/>
</Page>

I found the solution through MSDN:我通过MSDN找到了解决方案:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    MyUserControl rtn = null; 

    page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
        Grid rootGrid = page.Content as Grid;

        if(rootGrid != null) {
            var controls = rootGrid.Children.OfType<MyUserControl>();

            foreach(MyUserControl control in controls)
            {
                if(control.Tag == tag) rtn = control;
            }
        }
    }).AsTask().Wait(); //Runs the dispatcher synchronously

    return rtn;
}

Reference post: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/e15d4852-a601-4bd6-88b4-42480fd71e70/win-rt-awaiting-the-dispatcherrunasync?forum=winappswithcsharp参考帖子: https : //social.msdn.microsoft.com/Forums/windowsapps/en-US/e15d4852-a601-4bd6-88b4-42480fd71e70/win-rt-awaiting-the-dispatcherrunasync?forum=winappswithcsharp

EDIT: A note, though, if this is to be used throughout the application: you may have to do a check to see if the method already has thread access.编辑:但是,请注意,如果要在整个应用程序中使用它:您可能需要检查该方法是否已经具有线程访问权限。 I haven't found an elegant way to do this as of yet, but the basics of it look like this:我还没有找到一种优雅的方法来做到这一点,但它的基础看起来像这样:

public static MyUserControl GetControlByTag(this Page page, int tag) {
    Grid rootGrid = page.Content as Grid;

    if(page.Dispatcher.HasThreadAccess) {
        //Code to run
    }
    else {
        page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
            //Code to run
        }).AsTask().Wait();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM