How to get a certain UI control from two classes

0

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?

c#
xaml
uwp
asked on Stack Overflow Dec 31, 2018 by Mayson • edited Jan 1, 2019 by Mayson

2 Answers

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.

answered on Stack Overflow Dec 31, 2018 by Luis Alves
1

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.

answered on Stack Overflow Jan 1, 2019 by Nico Zhu - MSFT • edited Jan 1, 2019 by Nico Zhu - MSFT

User contributions licensed under CC BY-SA 3.0