22

I was wondering how one could access the current instance of the main page from a different class in a C# Windows Store app.

Specifically, in a Windows Store app for a Surface RT tablet (so, limited to RT API) I want to access mainpage methods and UI elements from other classes.

Creating a new instance works, like this:

MainPage mp = new MainPage();
mp.PublicMainPageMethod();
mp.mainpageTextBlock.Text = "Setting text at runtime";

in that it exposes the methods / UI elements, but this can't be the proper procedure.

What is the best practice for accessing methods and modifying UI elements on the main page at runtime, from other classes? There are several articles about this for Windows Phone but I can't seem to find anything for Windows RT.

Charles
  • 50,943
  • 13
  • 104
  • 142
Danny Johnson
  • 495
  • 1
  • 7
  • 20
  • 1
    I would say best practice is not to do that. Best practice would be to use a pattern such as MVVM which keeps things you might want to call out of the UI. http://en.wikipedia.org/wiki/Model_View_ViewModel – dkackman Jul 09 '13 at 19:29
  • 1
    I'd agree with using the MVVM pattern. At the very least, you could make events on the classes that would otherwise update your main form. Have your main form subscribe to these events, and allow it to handle its own UI in response to the events. – Curtis Rutland Jul 09 '13 at 19:34

3 Answers3

51

I agree that it's better to use MVVM pattern, but just in case you need to get current page you can do it as follows:

  var frame = (Frame)Window.Current.Content;
  var page = (MainPage)frame.Content;
takemyoxygen
  • 4,294
  • 22
  • 19
  • 4
    Holy god how I have wondered how to do this. You sir, are a champ and a gentleman. Thank you very much indeed. – MartinJH May 08 '16 at 16:28
1

If you're using MVVM, you can use the Messenger class:

MainWindow.xaml:

using GalaSoft.MvvmLight.Messaging;

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new MainViewModel();
    Messenger.Default.Register<NotificationMessage>(this, (nm) =>
    {
        //Check which message you've sent
        if (nm.Notification == "CloseWindowsBoundToMe")
        {
            //If the DataContext is the same ViewModel where you've called the Messenger
            if (nm.Sender == this.DataContext)
                //Do something here, for example call a function. I'm closing the view:
                this.Close();
        }
    });
}

And in your ViewModel, you can call the Messenger or notify your View any time:

Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, "CloseWindowsBoundToMe"));

pretty easy... :)

Rudi
  • 926
  • 2
  • 19
  • 38
-1

I prefer a Delegate/Event, that way you have no Direct Access on the class.

public MainWindow()
{
    StartWindowUserControl.newBla += StartWindowUserControl_newBla;

    private void StartWindowUserControl_newBla()
    {

and

public partial class StartWindowUserControl : UserControl
{
    public delegate void newBlaDelegate();
    public static event newBlaDelegate newBla;

MethodA()
{
   new();
Master117
  • 660
  • 6
  • 21
  • Why create a new delegate? Just use `Action`. Also, you can't name an action `new` as `new` is a keyword. – Servy Jul 09 '13 at 19:42
  • just took something from my code and deleted the later parts, yeah new is forbidden, forgot that when deleting ^^ and why not use new Delegates? I think thats a matter of taste – Master117 Jul 09 '13 at 19:51
  • 1
    When I see an event of type `Action` I know immediately what the signature is. It's a parameter-less `void` method. When I see a `newBlaDelegate` type event I have no idea what the signature is; I have to go look it up. Additionally using `Action`/`Func` whenever possible makes it easier to pass around delegates rather freely and use them interchangeably if they have the right signature, rather than worrying about converting from one delegate to another when the signatures match perfectly. – Servy Jul 09 '13 at 19:53
  • But newBlaDelegate might aswell have an parameter, also you can use the class as lib, if you have an own Delegate you can "catch" it in different packages making you class more adaptable. – Master117 Jul 09 '13 at 19:59
  • If you need a parameter then you can still use `Action`/`Func`. If you, for example, have a single string parameter you can use an `Action`. How is using a custom delegate more "adaptable"? In what context would you use it to adapt that you couldn't through one of the system defined delegates? – Servy Jul 09 '13 at 20:10
  • If i use Action i have to do something like, public class Name { DisplayToWindow() public class testTestDelegate { public static void Main() { Name testName = new Name("Koani"); Action showMethod = testName.DisplayToWindow; showMethod(); } Now i have to set the Method that gets executed in testtestDelegate, meaning i can't use testtestDelegate without Name, with a custom Delegate and += i can set the method that gets called in another class, meaning i can use testtestDelegate without Name in another project, calling another Method – Master117 Jul 09 '13 at 20:17
  • The syntax for creating an instance of the delegate or calling it is identical for a system defined delegate and your user defined delegate. There is nothing you gain in that regard. Also, you aren't null-checking your event before firing it in your answer. – Servy Jul 09 '13 at 20:20
  • Edited my last comment, submitted by accident, and you are right null checking is required – Master117 Jul 09 '13 at 20:21
  • That example doesn't compile for a *lot* of reasons. On top of that, it's not clear at all what you're trying to do, or how it would be any different with a custom delegate. As I said before, the syntax for creating an instance of a delegate is no different for a user defined custom delegate than one defined by the BCL. – Servy Jul 09 '13 at 20:24
  • Hmm i guess you are right, i mean thats why Action is there, however what do you do if you have a lot of delegates? – Master117 Jul 09 '13 at 20:27
  • What do you mean, you *shouldn't* have a lot of delegates; that's my point. You should just be re-using Action/Func. If you mean lots of instances of one, then why is it any harder to work with than a custom delegate? – Servy Jul 09 '13 at 20:29
  • But how can i reuse Action if i need three delegates with different types of parameters in a single class? – Master117 Jul 09 '13 at 20:33
  • `Action` `Action` `Action` – Servy Jul 09 '13 at 20:34
  • I totally forgot about overloading of delegates, well thank you for enlighting me, still i don't like Generics that much. – Master117 Jul 09 '13 at 20:37
  • You should learn to; it's a pretty essential feature to be at least reasonably comfortable with if you're going to use C# much at all. Also, that's not overloading at all, that's just using generics. – Servy Jul 09 '13 at 20:40
  • I know how to use generics and often use them i just well, don't like them. – Master117 Jul 09 '13 at 21:10