0

I am trying to create a windows Metro App. But at the moment I can't go further because I need a possibility to trigger an event or call a method from the settingsflyout at the mainpage. But I don't have an mainpage object at the settingsflyout and I don't know how to get one. Have someone an idea how to do this?

Damien
  • 37
  • 6

1 Answers1

2

Well, there are some tricks you should know about first. Some events, like the click event of a button, cannot be triggered programmatically. There are some API calls, such as ShowUI() which cannot be invoked from event handlers which are not a result of a user-invoked event in the call stack. Not sure if that makes sense, it's just a special thing in WinRT. But let's pretend you aren't trying to invoke the click event of a button or any API that requires the user to initiate it.

There are several ways to do what you want. And this is really more of a C# discussion than a Windows Runtime or XAML discussion. But, that's okay. It's an important issue.

You are having this problem because the flyout is out of scope of the current page. A flyout is not a child of a page, it is just something that is invoked by a page. There is not a reference to the page in the flyout or the flyout in the page. So how do we communicate?

Option 1

You could create a public static event in app.xaml.cs that is raised by the flyout and handled by the page. Since external classes cannot raise events of other classes, your app.xaml.cs would also need a public static method that triggers the event (that can be called by the flyout).

Sort of like this

public static event EventHandler MyEvent;
public static void RaiseMyEvent()
{
    if (MyEvent != null) MyEvent(null, EventArgs.Empty);
}

This is a good solution because it lets the flyout talk to whatever page calls it without knowing the page that called it. This means two pages could invoke the flyout and both use the same pattern to react to it.

Warning: when you subscribe to the app.xaml.cs event in your page, do not, I repeat, do not forget to unsubscribe to it when you navigate away from the page. Remember, garbage collection will not remove from memory any object which has a strong reference to another - including an event handler. So, with your += logic, be sure to include your -= logic, too. :)

Option 2

If there is no reason for you to call the flyout from more than one page you can always put the static method on the page itself. The flyout could call this method and invoke some type of action on your page without having a reference to the instance that called it. As long as you don't have more than one instance of the page, this can work fine.

Option 3

The reverse of Option 2 is to subscribe to an event on the flyout. As long as you heed the warning to unsubscribe to this event when the page navigates away, it's fine to do it this way.

Note: all three options work just fine. Anyone telling you that they are bad ideas are really just warning you that they are the types of approaches that you can get wrong easily. If it were me picking between then, I would choose option 1. But if you chose option 2 or 3, I would not think you made a mistake, just a developer preference sort of choice. Just remember to unsubscribe.

Option 4

The high end approach is to use a messaging service like PubSubEvents from Microsoft's patterns and practices. I describe this in detail in module (07) Prism - Part 2. There's also a messaging service in MVVM Light which is fine to use. These are event aggregators which are accomplishing in an abstract way what I describe in Option 1. This is not superior. But it is repeatable and less likely to be implemented with a strong reference. If this sounds interesting to you then you can use a messaging service to accomplish the task you are describing in your question.

Find module 7 here: http://blog.jerrynixon.com/2014/10/ready-to-learn-developing-universal.html

Option 5+

There are other ways, of course. You could pass a reference of your page in the constructor of your flyout - though this is so prone to error and misuse, I would not recommend it. You could use the VisualTreeHelper to spelunk down the CoreWindow's root element to find the page and invoke something with reflection. Again, technically possible, but not recommended because it's a mess of code and so easy to get wrong.

Most XAML developers in your situation just use a static event. Some live and die by Messaging. I just like to do what works. All these options work, including the reflection craziness. Ultimately, the choice is yours as the developer. Only you know the details of your app. I hope this helps.

Best of luck!

Jerry Nixon
  • 31,313
  • 14
  • 117
  • 233
  • thanks for your help ... your answere helped me to find the right way ... I have used this solution http://stackoverflow.com/a/6716539/2890223 – Damien Jan 10 '15 at 19:35