MEF & Silverlight: How do I navigate to a page in another XAP? - silverlight

I'm very lost on how to do this.
I understand MEF and can load services and classes from another XAP using the ubiquitous DeploymentCatalogService found in many blog posts. What I don't understand is how to actually load and navigate to a PAGE from another XAP.
What I'd like to do is have my main application be able to call the NavigationService and provide it with the name of a Page that should exist. Like:
NavigationService.Navigate(new Uri("/Test", UriKind.Relative));
It's up to one of the other XAP files to provide this page to the application. However, I have no idea how to make this work. It seems like everyone is building up some complicated infrastructure to handle this situation and it's very annoying and overly complicated.
Is there an easy way to do this?

Some of the examples I've seen are more complicated than they need to be, but this is not a simple task. It took me 2 days to break down the examples I could find before I really understood what is going on.
To do this you need to create minimum two classes.
A class that implements INavigationContentLoader, this will do all of the work.
A class that implements IAsyncResult. This object will passed around the INavigationContentLoader, so use it to keep track of what you are doing.
Your INavgiationContentLoader should do the following.
BeginLoad
Test if the Uri belongs to the current XAP or a XAP that has already been loaded.
If not, use DeploymentCatalog to download the XAP. Store the DeploymentCatalog in an AggregateCatalog.
Create the page for the given Uri using an ExportFactory. Give yourself a property on your IAsyncResult to hold this.
If the operation has not been cancelled, execute the callback parameter.
CanLoad
You can try to put some logic in here to test of you have access to the specified XAP, or you can just return true and be done with it.
CancelLoad
Set a state within the IAsyncResult to let you know the operation has been cancelled.
EndLoad
Get the page that was stored in the IAsyncResult, wrap it in a LoadResult and return.
All pages that will be loaded by this INavgiationContentLoader will need to be marked with an ExportAttribute so that ExportFactory can find them.
Edit
My INavigationContentLoader
http://pastebin.com/cT1mJ4Ve
My IAsyncResult
http://pastebin.com/xHWHT4pr
ExportAttribute to use on pages. You need this on all pages, even the ones in the local XAP.
http://pastebin.com/nTJ27mWz
IExportPageMetaData. This is the contract that MEF uses.
http://pastebin.com/8fdwx2Kn
How to use:
Declare your navigation:Frame like this
<navigation:Frame x:Name="ContentFrame"
Source="/Home"`
Grid.Column="1">
<navigation:Frame.ContentLoader>
<navUtil:DynamicContentLoader />
</navigation:Frame.ContentLoader>
</navigation:Frame>
HyperlinkButton to a page from another XAP.
<HyperlinkButton Content="Page from another XAP"
NavigateUri="/NavigateUriFromExportPageAttribute"
navUtil:DynamicContentLoader.Xap="UriToOtherXap" />
HyperlinkButton to a page from this XAP.
<HyperlinkButton Content="Page from this XAP"
NavigateUri="/NavigateUriFromExportPageAttribute" />
You do not need a UriMapper, nor do you need to put the Path of the Page.xaml. MEF will read the ExportPageAttribute from the page and find the Uri that way.

Take a look to Navigating between Pages in Different Xaps (by using MEF) post on http://www.silverlightshow.net. It's exactly what you need. Source for post is also available.

Related

Custom logic in Cakephp 3.0 view

This is for CakePHP 3.0
I want to encapsulate some nontrivial php logic to be called (reused) several times within one .ctp file for one controller action. I'm trying to figure out the most elegant way of doing it.
I have a few thoughts, none of which seem very elegant:
$this in the CTP file execution context is class View. Put methods on the View class to call as $this->function() within the .ctp file. This seems like the wrong division of labor, especially since helpers seem designed for this. Plus the functions would be exposed to all ctp files.
Create a helper. This seems like the "best" way to go, but that helper is always loaded and exposed to all .ctp files, which seems like it violates containment since the logic is only relevant to one action's view. In the absence of a better solution, this is the route I'm taking.
Create a subclass of View for this element/model and put the logic there, to be accessed as in (1). This seems like the most elegant solution, but it appears that subclassing View is intended for alternate media (eg PDF), and I can't see how to direct Cake to use that class when manufacturing the view for a given controller's action.
Shove the function inline in the .ctp file. I'm not even sure if this will work correctly, and it seems ugly to put functions in a .ctp file.
Any advice?
Well, you're not explaining what kind of super complex logic you want to use there so I would say go for 3). It is very well possible, you can load helpers in a view files:
$this->loadHelper('MyFancyLogic');
You can also checkout view cells. But again, you're not explaining what problem exactly you try to solve it's hard to recommend anything specific. So I would say it's a helper or a view cell.

How to get all the AutomationIDs of a WPF application in a file?

In automation of a WPF application (using UI Automation; VSTS 2010), we were adding all the Automation IDs in a Resource File manually and then access it one by one. Considering the application can expand any time, manually adding these IDs can become tedious.
So, is there any tool available which can create this for us? i.e. Get all the ids in a hierarchical format and store it in a file (xml or csv), and then we could parse it whenever required.
I was hoping for a tool like UISpy, which not only can spy all the elements but also export the same.
Do such tools exist? Or is there any alternate approach?
Any valuable feedback is highly appreciated.
Thanks!
I do like this:
public static class AutomationIds
{
public static readonly string MyDataGridId= Create();
private static string Create([CallerMemberName] string name = null)
{
return name;
}
}
<DataGrid AutomationProperties.AutomationId="{x:Static local:AutomationIds.MyDataGridId}"
... />
Then in tests
var dataGrid = window.Get<ListView>(AutomationIds.MyDataGridId);
Assign the automation IDs directly in XAML, then parse XAML files since they are XML after all...
Let's see...
First, I think that your data is not hierarchical - just because a control can be dynamically assigned to be a child of another.
If we change the problem to a subset: "how can we get a hierarchical view of the controls at a time t?" then we can answer this with MS UIA, and say, using a simple RawViewWalker (just a simple breadth-first search on the walker, starting from your main window will do - of course while the application is running so that UIA can reach and query it).
But this subset will not satisfy your initial question, because you'll probably see a portion of your whole ui collection (since some will be hidden / not activated yet at time t).
So it becomes very hard to use a UIA based tool (such as uispy) because then you'll have to set the application view to different states to reach all the controls in your application at different times t1, t2...
I would suggest parsing all your xmls at the same time and build a complete tree of the application's "static" control map, which I believe would be closest to what you're asking for.
Given that this is an old question, I doubt it matters anymore, but just wanted to make the distinctions here.

Sharepoint's Client Object Model with Silverlight, is it possible to load web.Language with executeQuery?

Is this:
Web web = context.Web;
context.Load(web, w => w.Language);
context.ExecuteQuery();
or something similar in order to load web.Language with context.ExecuteQuery() possible in a silverlight client? The above code was taken from
http://www.dev4side.com/community/blog/2011/1/5/incorrect-dates-taken-from-sharepoint-2010-client-object-model.aspx
When I do so, instantiating the web's Language property always yields
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException
Btw, this code is in an extra thread (not the UI thread). I know that there is context.loadQueryAsync() but I already have an extra thread and would like to keep things together.
As far as I've tried this code works ok. Do you maybe access some other properties of the Web object that are not loaded? You'd have to include them also in your load method.

Preferred way of creating links with backbone.js

I'm trying to wrap my head around backbone.js but I'm finding it hard due to the lack of (IMO) good examples.
First of all, what is the best way of getting a link to an object.
If I want to get the edit url of an Album model I could do album.url() + '/edit', is this really the best way?
Also, I'm trying to make my application work 100% without javascript so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
I'm thinking I create normal URLs and use jQuery.live to call router.navigate in backbone.js
I never got this to work however, when I call router.navigate('/albums/2', true) the URL changes but my show action is never called. If I refresh it's called so the route is matched.
What am I missing?
The basic answer, which is kind of frustrating, is "there is no preferred way!". Backbone.js doesn't tell you how to set up links, you can do it any way you like. I found this flexibility just as annoying as you do, at least at first.
So here's the way I'm approaching this on my current project, with the (big) caveat that this is just one of many ways to do things in Backbone:
For the most part, I don't use actual links. There's no explicit reason not to, but it means you have to keep track of a bunch of URL strings that have to be consistent. I would rather stick all the URL formatting in my routers and not deal with it elsewhere.
To open a new "top-level" view, like an editing screen, I set something that fires an event. In the application I'm currently working on, I have a global State model, and to open a new view I call state.set({ topview: MyTopView }). This causes the state object to trigger change:topview.
Any piece of the UI that needs to change when the top-level view changes has an update method bound to change:topview. When the event fires, they look at state.get('topview') and update as necessary.
I treat my routers as only marginally specialized parts of the UI - they're essentially views that render in the browser address bar, rather than the window. Like other views, they update the state object on UI events (i.e. a new URL), and like other views, they listen to the state object for changes that cause them to update. The logic that the editing screen has the URL albums/<albumid>/edit is fully encapsulated in the router, and I don't refer to it anywhere else.
This works well for me, but it adds an entirely new pattern, the global State object, to the Backbone structure, so I can hardly call this the "preferred" approach.
Update: Also note that .url(), in the Backbone idiom, refers to the model's URL in the back-end API, not the front-end URL (it's not like Django's get_absolute_url). There is no method in the default Backbone setup that gives you a user-facing URL for your model - you'd have to write this yourself.
Also, I'm trying to make my application work 100% without javascript; so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
you can do exactly this w/ pushState. just enable it in your Backbone.history.start call:
Backbone.history.start({pushState: true})
this tells Backbone to use the HTML5 History API (a.k.a. "PushState"), which uses full URLs exactly like you're wanting.
read up on the history api here: http://diveintohtml5.ep.io/history.html
and I wrote up a 2 part series on using pushstate w/ the second part focusing on progressive enhancement in backbone, to do what you're needing:
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-1-introducing-pushstate/
and
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-2-progressive-enhancement-with-backbone-js/
hope that helps :)

WP7 NavigationService.Navigate pass a pointer without using global variables?

I am navigating to page X in WP7. I have an object (let's call it banana) in my ViewModel, which is where the NavigationService.Navigate call is being made. Page X needs a reference to the banana. How can I do that?
The answer to this question recommends using the global App class. Not a good option for me because I might have multiple instances of the class of page X, and I wouldn't want to confuse other instances if they are later navigated to.
I would also prefer not to have to serialize the banana.
If there could be multiple instances of the page then you'll need to pass any parameters it needs as part of the querystring in the Uri you use for navigation.
You can either use the query string (to send the id, for example) as suggested by #Matt, and you could also send the object itself via a message for example, you can use the Messenger class from MVVM Light for that.
Hope this helps :)

Resources