How to get a certain UI control from two classes

喜欢而已 提交于 2021-01-29 07:21:09

问题


I'm developing a UWP application with two window pages on two separate screens.

It's include:

  • Mainpage.xaml
  • Mainpage.xaml.cs
  • Page2.xaml
  • Page2.xaml.cs

My scenario:

  1. get the mouse position(X) while moving on the secondary screen (Page2).
  2. write it in the text block on the first screen (MainPage), Changing at the same time.

In MainPage.xaml

<Page
    x:Class="LineDraw.MainPage"
    xmlns:local="using:LineDraw"
    ...
    ..

    <Grid>

    <TextBlock Name="textblock" Text="N/A" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="100" />

    </Grid>
</Page>

In MainPage.xaml.cs

 public sealed partial class MainPage : Page
    {   
        public double Xpage2;

        public MainPage()
        {
            this.InitializeComponent();
            newpage();   
        }

        private async void newpage()
        { 
            int NewWindowid = 0;
            int Windowid = ApplicationView.GetForCurrentView().Id;
            CoreApplicationView newView = CoreApplication.CreateNewView();
            await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                Frame newframe = new Frame();
                newframe.Navigate(typeof(Page2), this); // this means existing MainPage object.
                Window.Current.Content = newframe;
                Window.Current.Activate();
                NewWindowid = ApplicationView.GetForCurrentView().Id;
            });

             bool available = ProjectionManager.ProjectionDisplayAvailable;

             ProjectionManager.ProjectionDisplayAvailableChanged += (s, e) =>
             {
               available = ProjectionManager.ProjectionDisplayAvailable;
             };

            await ProjectionManager.StartProjectingAsync(NewWindowid, Windowid);
        }

        public void copyX(double Xpage2)
        {
            textblock.Text = $"X = {Xpage2}";  
        }
}

In Page2.xaml.cs

 public sealed partial class Page2 : Page
    {      
        MainPage mainpage;
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            mainpage = e.Parameter as MainPage;
            base.OnNavigatedTo(e);
        }

        public Page2()
        {
            this.InitializeComponent();    
            Window.Current.CoreWindow.PointerMoved += CoreWindow_PointerMoved;    
        }

        public void CoreWindow_PointerMoved(CoreWindow sender, PointerEventArgs args)
        {
            Point ptr = args.CurrentPoint.Position;
            double Xpage2 = ptr.X;
            mainpage.copyX(Xpage2);

        }

I did the code above but the result is the following error:

System.Exception
  HResult=0x8001010E
  Message=The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

I want to get the textblock(UI control) in main.xaml from Page2.xaml.cs. I need a solution , How can I do that?


回答1:


You're trying to run a method (mainpage.copyX()) that has been running in another context. I don't know why you created another view, if you can just run this code on the MainView of CoreApplication. In MainPage.xmal.cs:

await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
     Frame newframe = new Frame();
     newframe.Navigate(typeof(Page2), this);
     Window.Current.Content = newframe;
     Window.Current.Activate();
     NewWindowid = ApplicationView.GetForCurrentView().Id;
});

await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
     Point ptr = args.CurrentPoint.Position;
     double Xpage2 = ptr.X;
     mainpage.copyX(Xpage2);
});

If you create another view, you need somehow share this resource in order for everyone execute on the same context.




回答2:


For your scenario, the better way is sending message via MessagingCenter. MessagingCenter is used to pass parameter between two class. And I have create code sample base on your code that you could refer.

MainPage.Xaml.cs

private async void newpage()
{
    int NewWindowid = 0;
    int Windowid = ApplicationView.GetForCurrentView().Id;
    CoreApplicationView newView = CoreApplication.CreateNewView();
    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame newframe = new Frame();
        newframe.Navigate(typeof(OtherPage), this); // this means existing MainPage object.
        Window.Current.Content = newframe;
        Window.Current.Activate();
        NewWindowid = ApplicationView.GetForCurrentView().Id;
    });

    bool available = ProjectionManager.ProjectionDisplayAvailable;

    ProjectionManager.ProjectionDisplayAvailableChanged += (s, e) =>
    {
        available = ProjectionManager.ProjectionDisplayAvailable;
    };

    await ProjectionManager.StartProjectingAsync(NewWindowid, Windowid);
    SubMessage();
}

private void SubMessage()
{
    MessagingCenter.Subscribe<OtherPage, string>(this, "Tag", async (s, arg) =>
    {
       await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            textblock.Text = arg;
        });

    });
}

OtherPage.Xaml.cs

public OtherPage()
{
    this.InitializeComponent();
    Window.Current.CoreWindow.PointerMoved += CoreWindow_PointerMoved;
}

public void CoreWindow_PointerMoved(CoreWindow sender, PointerEventArgs args)
{
    Point ptr = args.CurrentPoint.Position;
    double Xpage2 = ptr.X;
    MessagingCenter.Send<OtherPage, string>(this, "Tag", Xpage2.ToString());
}

And you could copy the MessagingCenter class directly from the above link. For more detail you could refer MessagingCenter official document.



来源:https://stackoverflow.com/questions/53991071/how-to-get-a-certain-ui-control-from-two-classes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!