DeutschEnglish

Apr 21

Implementing Snapped View in Windows 8.1 Apps

If you’ve ever developed a Store App for Windows 8, you might know the LayoutAwarePage class that is added automatically to newly created project in Visual Studio. This class takes care of detecting changes in the device’s orientation or the App’s current size and defined visual states that can be referenced in each page. This allows to display different page contents in full screen, Snapped and Fill view.

In Windows 8.1, there is no dedicated Snapped and Fill view, since the user may freely position two Apps besides each other (instead of being resticted to 25%/75% or 50%/50% in Windows 8). Nevertheless it might be useful for most Apps to react to different device orientation and App width (for example, by showing a reduced user interface when the App is displayed in split-mode and takes up less than 50% of the totally available screen width).

Unfortunately, no ready-made base class for detecting App size and orientation is auto-created in Windows 8.1 Store App projects, which means you’d have to create one on your own! This can actually be achieved in a few simple lines of code. I suggest you create an abstract base class each page within your App can inherit from, in the following example I’ll call it LayoutAwarePage, just like the one we’re used to from Windows 8 projects.

Every time either the orientation or the App’s width changed the window’s SizeChanged event is fired, so we register to this event (and unregister when the page is unloaded):

public abstract class LayoutAwarePage : Page
{
	public LayoutAwarePage()
	{
		this.Loaded += Page_Loaded;
		this.Unloaded += Page_Unloaded;
	}

	private void Page_Loaded(object sender, RoutedEventArgs e)
	{
		SetCurrentVisualState();
		Window.Current.SizeChanged += Window_SizeChanged;
	}

	private void Page_Unloaded(object sender, RoutedEventArgs e)
	{
		Window.Current.SizeChanged -= Window_SizeChanged;
	}

	private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs e)
	{
		SetCurrentVisualState();
	}

	private void SetCurrentVisualState()
	{
		//TODO
	}
}

As you can see, all we do within the event handler is calling a method that shall register the current visual state, such that the current page can make use of it. In addition, this method is also called right in the beginning when loading the page to make sure we’re starting up with the correct visual state registered, since the SizeChanged event is not called on page load.

The core part of this solution is the SetCurrentVisualState method itself, and even this one is rather straightforward:

private void SetCurrentVisualState()
{
	string visualState = String.Empty;
	ApplicationView window = ApplicationView.GetForCurrentView();
	double width = Window.Current.Bounds.Width;

	if (window.IsFullScreen)
	{
		if (window.Orientation == ApplicationViewOrientation.Landscape)
			visualState = "FullScreenLandscape";
		else
			visualState = "FullScreenPortrait";
	}
	else
	{
		if (width < 600)
			visualState = "Snapped";
		else
			visualState = "Filled";
	}

	VisualStateManager.GoToState(this, visualState, true);
}

All we do is to first check whether the App runs in full screen mode and, if so, in horizontal or landscape mode, or if not whether the App’s width matches some criteria. In this case I decided to define a Snapped mode that comes into play whenever the App is narrower than 600 pixels. The last line of code actually tells the VisualStateManager to pass the recently defined visual state to the current page, since the page should react to this state change by re-arranging its contents.

Now any page that inherits from our LayoutAwarePage can take advantage of this visual state registration and adapt its content accordingly. Actually, this works the same way as in Windows 8 Apps, by referencing VisualState objects.

I decided to keep the following example simple – all it does is showing one of two text fields, depending on whether Snapped mode is active (meaning the App takes less than 600 pixels in width) or not:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

	<Grid x:Name="DefaultGrid" Visibility="Visible">
		<TextBlock>Default contents</TextBlock>
	</Grid>

	<Grid x:Name="SnappedGrid" Visibility="Collapsed">
		<TextBlock>Snapped contents</TextBlock>
	</Grid>

	<VisualStateManager.VisualStateGroups>
		<VisualStateGroup x:Name="ApplicationViewStates">
			<VisualState x:Name="Snapped">
				<Storyboard>
					<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DefaultGrid" Storyboard.TargetProperty="Visibility">
						<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
					</ObjectAnimationUsingKeyFrames>
					<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SnappedGrid" Storyboard.TargetProperty="Visibility">
						<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
					</ObjectAnimationUsingKeyFrames>
				</Storyboard>
			</VisualState>

			<VisualState x:Name="Filled">
				<!-- add Storyboard -->
			</VisualState>

			<VisualState x:Name="FullScreenLandscape">
				<!-- add Storyboard -->
			</VisualState>

			<VisualState x:Name="FullScreenPortrait">
				<!-- add Storyboard -->
			</VisualState>
		</VisualStateGroup>
	</VisualStateManager.VisualStateGroups>

</Grid>

Of course, also the other VisualState tags could be filled with storyboards, for example to display different content in landscape and portrait mode.

The nice thing about this implementation is that is works with pages that have been developed for Windows 8 without any changes, since it makes use of the well-known Snapped, Filled, FullScreenLandscape, and FullScreenPortrait visual states.

However, whats even better: You can define as many different visual states as you want, and (since they are only identified by a string property in both XAML and codebehind) name them anything you’d like! This means that we could easily add more branches in the decision tree inside the SetCurrentVisualState method, for example to predefine several width intervals in which the App’s content shall be layout out differently.

Permanent link to this article: http://www.mobilemotion.eu/?p=1029&lang=en

Apr 16

Problematic auto-deployment of Win 8.1 start screen layout

This one might be interesting for business users and system admins, but also for developers who want to test certain procedures on Windows 8.1 machines:

We all know how users can personalize their Win 8 start screen – pinning applications to start screen tiles, adjust tile sizes, group tiles, apply titles to certain groups, and so on. It is possible to export the start screen layout and re-use it later by using two new PowerShell commands:

Export-StartLayout –Path .xml -As XML

export the current layout to an XML file. The syntax is not very advanced, you can easily take a look at how Windows encapsulates all your tiles by opening it using notepad. To restore this exact layout, use

Import-StartLayout -LayoutPath .xml

The reason for specifying the export format as XML is that it is theoretically possibly to use a binary format (Export-StartLayout –Path .bin -As BIN) instead, however the following trick does not work with this format, so I suggest staying with XML.

Manually importing such a layout file is cool for testing and developing purposes, but in production environments you’ll like to assign the exported layout to certain users in order to specify their initial start screen appearance. This can be achieved through setting the Start Screen Layout group policy that accepts a layout XML file (no BIN file, as mentioned above) and automatically applies that during Windows login. For detailed instructions, see http://technet.microsoft.com/en-us/library/dn467928.aspx.

Nice feature, but unfortunately still a bit buggy: If your start layout contains secondary live tiles belonging to any App, and you assign a layout XML file to a machine that has the same Apps installed, these live tiles won’t update automatically.

Another issue concerns group titles: If you apply header texts to certain groups of tiles, export the layout to an XML file, and use this file as basis for the above-mentioned group policy, under certain circumstances these headers are not shown. The problem occurs only with custom-made Apps that are not yet installed on the target machine: On the first login, the group policy applies the layout file to the start screen. If the custom Apps are not yet installed, their tiles (and therefore the groups containing these tiles) can not be created, and of course the group headers are also missing. Afterwards, installation of these Apps starts, and after is has finished the start screen is automatically adapted: The newly installed Apps’ tiles are created and automatically assigned to groups as specified in the layout file, however no group headers show up. It seems that these headers can only be created on the first startup, since restarting the machine does not solve the problem. I reported this issue to the Technet forums.

Permanent link to this article: http://www.mobilemotion.eu/?p=1023&lang=en

Apr 10

Separating item groups in a Win 8.1 GridView

The short story:

Today, I was struggling with a Windows 8.1 App in order to add a 50 px margin between the different groups in a grouped GridView control.

The long story:

The aim was to create a screen that somehow reminds of the Windows 8 start screen: Data is presented in the form of various tiles belonging to different groups, each group shall get it’s own title and be separated from the neighboring groups by a margin of 50 pixels. Started off easily using a standard GridView that’s ItemSource is bound to a CollectionViewSource with the IsSourceGrouped attribute set to true (mandatory to achieve grouped data presentation).

As ItemsPanelTemplate, an ItemsWrapGrip was used to lay out an arbitrary number of tiles. Finally, the headers are designed by filling the GroupStyle.HeaderTemplate:

<GridView.GroupStyle>
	<GroupStyle>
		<GroupStyle.HeaderTemplate>
			<DataTemplate>
				<TextBlock Text="{Binding HeaderText}" />
			</DataTemplate>
		</GroupStyle.HeaderTemplate>
	</GroupStyle>
</GridView.GroupStyle>

Everything works fine so far, items and header texts are layed out as desired. Now what about adding 50 pixels of empty space between the groups?

The quick but dirty solution:

ItemsWrapGrid, which was used as ItemsPanelTemplate, offers the GroupPadding attribute: This allows to add 50px to the right border of each group, for example:

<GridView.ItemsPanel>
	<ItemsPanelTemplate>
		<ItemsWrapGrid GroupPadding="0,0,50,0"/>
	</ItemsPanelTemplate>
</GridView.ItemsPanel>

The problem is that this is a padding, not a margin, and as such adds 50 pixels within each group, not outside of it. Not a big deal, except if each group features a background color different from the page’s general background – in this case, the colored background panel extends 50 pixels to the right. To overcome this, there is another approach:

The complex solution (unfortunately, also not 100% satisfying):

Unfortunately ItemsWrapGrid does not offer a GroupMargin attribute (of course, Microsoft won’t make it too easy for us developers). The alternative is to define the desired margin within the GroupStyle:

<GroupStyle.ContainerStyle>
	<Style TargetType="GroupItem">
		<Setter Property="Margin" Value="0,0,50,0"/>
	</Style>
</GroupStyle.ContainerStyle>

Unfortunately, the GroupStyle.ContainerStyle is marked deprecated in Win 8.1 (according to http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.groupstyle.aspx) and has no effect when used together with panels of type ItemsWrapGrip. It does work, however, with other panels – you could, for example, use a VariableSizedWrapGrid as ItemsPanelTemplate, but this means re-thinking the tiles’ layout and adapting this to the new panel…

Well, no ideal solution here, but at least two potential approaches to follow. Let’s hope this topic is fixed soon!

Permanent link to this article: http://www.mobilemotion.eu/?p=1018&lang=en

Mar 30

An Anternative to WinRT’s NavigationHelper

This is a quick follow-up to the series of blog posts dealing with the difficulties of the built-in navigation framework of Windows Store Apps. If you’ve decided to replace WinRT’s navigation mechanism by a costum solution as suggested in Re-implementing WinRT’s navigation system, there is one more thing that needs to be updated in future projects that make use of your custom navigation framework: When creating a new Windows Store project from the defaul Visual Studio Templates, the automatically created views reference the NavigationHelper class that is located within the project’s Common namespace. This class provides (among others) a command that navigates to the previous page which can be bound to a back button included in any page.

The problem is, this command uses WinRT’s built in GoBack() method which should not be called any more because we have our own functionality for backwards navigation! An alternative approach for easy binding of visual back buttons, is to include all the necessary functions and commands in an MVVM setting:

Create a basic Viewmodel class that all other Viewmodels inherit from, in order to ensure that the desired functionality is available in all Views. This Viewmodel baseclass contains a GoBack command that simply calls your custom backwards navigation method and that references your CanNavigateBack() method (or whatever it’s called) as its CanExecute property.

Each page that shall contain a back button needs to reference a Viewmodel which inherits from this base class as its DataContext – then each back button’s Command property can simply be bound to the newly created GoBack command!

Permanent link to this article: http://www.mobilemotion.eu/?p=987&lang=en

Mar 18

Re-implementing WinRT’s navigation system

As discussed in the two blog posts Caching pages during navigation in Store Apps and Back-stack manipulation in Store Apps, there exist a few reasons for being unsatisfied with WinRT’s navigation framework. If you are thinking about implementing your own navigation service to be used in Windows Store Apps, here is a rough overview of all the things to keep in mind.

Note: This guide does not contain detailed instructions in form of code lines, but rather a general pattern that could be used to implement a custom navigation service. For a complete code sample, see my implementation of a dedicated navigation service as part of the MVVMbasics framework. The sources of the framework are available at CodePlex. The files NavigatorService.cs and BaseView.cs of the MVVMbasics TabletExtensions are of special interest as they contain the main logic described in the guide below!

Alright, let’s get started!

  1. First, I’d recommend to create a service class that will contain all navigation methods. The overall aim is to use only functionality incorporated within this service for navigation in the future, and be independent of the built-in navigation methods.
  2. Within this newly created navigation service, we’ll need some kind of back-stack. In case of an App that follows the MVVM pattern, this could be implemented in form of a list that holds both page types and Viewmodel instances for each visited page (e.g., two separate lists for page types and Viewmodel instances, or some kind of ordered Dictionary, or a list that contains items of a helper class each of which holds one page type and one Viewmodel instance, …)
    To realize the navigation mechanism, we need to internally rely on the current Frame’s built-in Navigate() method. Since this method does not allow to navigate to a specific page instance but only to specify the target page’s type, the idea is to store not the visited pages themselves, but only their types plus their Viewmodel instances. When returning to a previously shown page, a new instance of this page may be created, but the original Viewmodel instance must be assigned as this page’s DataContext in order to restore the page’s state.
  3. Of course, the navigation service must contain the two most important navigation methods: One for navigating forward (opening a new page that has not been opened before, or that has aready been closed), and one for navigating back (closing the current page and returning to the previously displayed page).
    1. The former might simply call the current Frame’s Navigate() method and pass the desired page’s type, as we’re used to from WinRT’s default navigation mechanism.
      An important addition is to add the page we’re navigating away from to the back-stack, meaning that both the page’s type and the connected Viewmodel’s current instance must be stored in the navigation service’s internal back-stack list. This must happen directly before navigating away from the current page, in order to ensure that the page’s last state (in form of the Viewmodel’s current state) is stored and can be retrieved later.
    2. The latter, let’s call it NavigateBack(), is a bit more difficult to define. Instead of using the current Frame’s GoBack() method as usual, we call Frame.Navigate() again, but this time pass the type of the page that is on top of the back-stack – this ensures that the previously shown page is reloaded.
      After this navigation has been completed (e.g., as reaction to the current Frame’s Navigated event), the newly loaded page’s DataContext property must be set to the Viewmodel instance that is on top of the back-stack.
      Of course, since we’re closing the currently shown page, this should not be added to the back-stack. Instead it is necessary to remove the top item (including both page type and Viewmodel instance) from the back-stack!
  4. Of course it’s possible to integrate further methods into the navigation service, including for example a CanNavigateBack() function, and back-stack manipulation functionality (RemoveBackEntry(), ClearBackStack(), and similar methods).
  5. We’re almost done – there is only one thing to keep in mind that is not directly connected to the custom navigation service class and therefore might easily be forgotton:
    Within each page’s OnNavigatedTo(), OnNavigatingFrom() and OnNavigatedFrom(), we can not rely on the NavigationEventArgs.NavigationMode flag any more to distinguish between forward and backward navigation! Instead, one option is to include a NavigationMode property within the navigation service class that can be read from within each page.

Permanent link to this article: http://www.mobilemotion.eu/?p=962&lang=en

Mar 12

Back-stack manipulation in Store Apps

Although Microsoft is constantly trying to consolidate Windows Phone and Windows Store APIs, there still exist a lot of differences between the two frameworks. I’ve recently blogged about the caching algorithm in page navigation of Windows Store Apps – a similar example, also related to navigation issues, is back-stack manipulation.

On the Windows Phone platform, one can easily call NavigationService’s RemoveBackEntry() method to remove the most recent page from the back-stack, or call the method multiple times to clear the entire back-stack. In Windows Store Apps, no such method exists – I’d like to discuss three potential workarounds for the existing WinRT API in order to simulate this behavior:

  • Cope with it and try to work around the existing limitations:
    As an alternative to real back-stack manipulation, you could simply call the GoBack() method multiple times to skip certain pages instead of removing them from the back-stack. Of course, this requires some logic that must be considered every time when navigating back – in practice, you might end up keeping your own back-stack in form of a list of all visited pages including a removed flag, and consult this list on each backwards navigation in order to calculate how many GoBack() calls are necessary to navigate to the desired target page.
  • Dig into the existing system and improve it:
    Of course, WinRT keeps an internal list of all visited pages. You could retrieve this as a string property by calling Frame.GetNavigationState(), adapt it to your needs and push it back into the system through Frame.SetNavigationState(). The problem is that the format of this string is not documented and might be changed in future versions of the framework.
  • Completely avoid the existing framework and reinvent the wheel:
    In order to keep a back-stack of all visited pages that may be directly manipulated, it would be necessary to implement the whole navigation strategy by yourself. There exist a few libraries and frameworks which do this and can be used, but it’s not that difficult to implement the necessary services on your own. This approach might be useful when trying to cope with other limitations of WinRT’s navigation framework too, as it could solve several problems at once.
    If you think about following this way: There will be another blog post (→ Re-implementing WinRT’s navigation system) explaining the approach in detail!

Permanent link to this article: http://www.mobilemotion.eu/?p=969&lang=en

Mar 08

Caching pages during navigation in Store Apps

The short story:

Each time you navigate back to a previously displayed page within a Windows Store App, a new instance of the page is created instead of re-using the previously used instance. In an MVVM environment, this also means that any Viewmodel connected to the page via the DataContext property is also re-instantiated – to verify that, simply set a breakpoint within the Viewmodel’s constructor and watch it being called again and again each time the page is reloaded. Shouldn’t pages and Viewmodels being cached, as long as we don’t explicitly call GoBack() to navigate away?

The long story:

It seems that this behavior is intended by Microsoft – but it can be configured by the developer! Each page provides a NavigationCacheMode property that can be set directly in XAML code to one of the following three options:

  • Disabled

    Represents the behavior described above – no cache of visited pages is maintained, pages and everything connected to them (e.g., Viewmodels referenced as DataContext) is re-instantiated on each visit.

  • Enabled

    Visited pages are cached, the developer can configure the maximum number of pages the chache should contain.

  • Required

    All visited pages are cached.

Unfortunately, the first option Disabled is the NavigationCacheMode properties default value. The easiest solution for the problem described above is to set it to Required in order not to worry about cache sizes. At least it seems so – however this results in a long list of further problems!

The even longer story of subsequent problems:

Setting the NavigationCacheMode property to either Enabled or Required solves our initial problem of continuous re-initialization of pages and Viewmodels. However, as a side-effect, all pages are cached until the App is terminated (or until the cache is full) – didn’t we want to remove a page from the cache when calling GoBack() to close it?

For really, really simple Apps that contain only of a few pages that are not nested there might be a simple solution: Set NavigationCacheMode="Required" only for the main page, and Disabled for all the other pages. This strategy fails as soon as one page offers methods for both navigating to another new page, and navigating back to the previously shown page: If set to Disabled when opening a new page, we will not be able to return to the current page without re-initialization. On the other hand, when set to Required, closing the page by calling GoBack() and opening it again later on, the instance that should have been closed is maintained…

Calling NavigationCacheMode="Disabled" from C# code before any GoBack() call does not solve that problem either, as it does not remove pages from the cache but only disables future caching attempts.

There must be a better way!

Well, not so sure about this one. I can think of the following approaches, either one not being the ideal, award-winning solution we’d like to see:

  • When closing a page (meaning, when calling GoBack(), as you should know by now), what about manually removing it from the cache?
    Since there is no built-in method for cache manipulation, this would require some workarounds. First, this approach requires the NavigationCacheMode property of all pages set to Enabled initially. Now, since we cannot remove a distinct item from the cache, we’d clear it at once – but before doing so, it’s important to set NavigationCacheMode="Required" for all those pages that shall remain cached, meaning all pages except the current one. Now, finally, we can clear the cache by setting the current Frame’s CacheSize property to 0.
    Not exactly brilliant, but you’ve been warned!
  • The only alternative I can think of is to quit relying on the WinRT Framework’s built-in page cache and navigation methods and implement all those by yourself. Sounds not much much easier than the first approach? Well, I’ve tried, and surprisingly it turned out to be not that difficult, although there are a few things to keep in mind.
    If you think about following this way: There will be another blog post (→ Re-implementing WinRT’s navigation system) explaining the approach in detail!
  • Of course, you might simply reference any third party library to do the navigation work for you. For example, my own MVVMbasics MVVM framework includes a distinguished navigator service that solves the problem described above (among many others), but there are plenty of other frameworks out there, available through NuGet!

Permanent link to this article: http://www.mobilemotion.eu/?p=955&lang=en

Mar 01

Looking behind Windows Phone’s RemoveBackEntry method

When searching the web for details about how to remove all items from the back stack of a Windows Phone App, most pages just tell you to call

if(NavigationService.CanGoBack())
	NavigationService.RemoveBackEntry()

When using this from a page’s code behind this is trivial, since NavigationService is a direct member of the current PhoneApplicationPage.

The question is: How to call this from any other code within your App? For example, in an MVVM structured App you will definitely not want this call in any page’s code behind, but rather within the page’s Viewmodel – or maybe in some centralized navigation service!

The currently active frame can be retrieved rather easily as follows:

PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;

However, we’re not quite there yet. PhoneApplicationFrame provides both a CanGoBack and a RemoveBackEntry method, so you might be tempted to just use those two directly:

PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
if (frame != null)
{
	if (frame.CanGoBack)
		frame.RemoveBackEntry();
}

Testing this on the Phone 7.5 emulator, I ended up inside an infinite loop: CanGoBack always returned true, and it seemed that RemoveBackEntry always removed the same page from the back stack again and again.

As a workaround for this bug, always remember to go down to the actual page instead of the frame. Here is the currect version:

PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
if (frame != null)
{
	PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
	if (page != null)
	{
		if (page.NavigationService.CanGoBack)
			page.NavigationService.RemoveBackEntry();
	}
}

Permanent link to this article: http://www.mobilemotion.eu/?p=936&lang=en

Feb 23

Update 1.2 for MVVMbasics Framework released

Yesterday, a new version of the MVVMbasics Frameworks has been published! The update contains bugfixes of the Command system as well as of the navigation within Windows Store Apps. In addition, 3 new functions within NavigatorService have been implemented: The newly introduced methods CanGoBack(), RemoveBackEntry() and ClearBackStack() the manipulation of back stack items – this applies to all three supported platforms.

The new version is available from the public Nuget-Repository. The sources can be downloaded from MVVMbasic’s CodePlex page.

Permanent link to this article: http://mvvmbasics.mobilemotion.eu/

Feb 23

[MVVMbasics] Avoiding duplicate Viewmodel instances in Windows Store Apps

Notice

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

In any MVVM application, it is necessary to link the Viewmodel to the View. In .NET/XAML, this is usually done by setting the View’s DataContext property to a new instance of the Viewmodel:

<PhoneApplicationPage.DataContext>
	<viewmodels:MyViewmodel />
</PhoneApplicationPage.DataContext>

When using MVVMbasics and the NavigatorService for easier navigation, it is not sufficient that the View knows about which Viewmodel instance to obtain the binding properties and commands from – in this case also the NavigatorService needs to know about the coupling between View and Viewmodel, in order to enable navigation to specific Viewmodels. Therefore the NavigatorService handles the binding of Viewmodels to Views internally, and it is not necessary to set DataContext manually.

The problem is: When using ReSharper, you are provided with extended Intellisense proposals, which for example allows automatic insertion of properties and commands within DataBinding markup extension tags – but this works only if you’ve specified the View’s DataContext at compile-time (from within XAML code).

In most cases, assigning the same Viewmodel class to a View twice (once by setting the DataContext property in XAML, once through MVVMbasics) does not lead to functional problems during application lifetime, but it allocates more memory than necessary (because actually two instances of the same Viewmodel class are created, one of which is not needed at runtime). Moreover, when using MVVMbasics 1.2 (or a newer version) in Windows Store Apps, this pattern has more severe drawbacks: In this case, whenever closing a page and returning back to the previously active page, this page’s Viewmodel instance is overwritten, including all its properties – which means that it is not possible to store data within a Viewmodel while navigating through the application! To avoid this, you should definitely leave the whole Viewmodel coupling task to the MVVMbasics framework and simply not set the DataContext property in your XAML pages.

Okay, but you’ll still want to benefit from ReSharper’s code fragment proposals, right? How can you accomplish this without setting a View’s DataContext at compile-time?

Simply use XAML design-time properties: First, make sure that the following namespace declarations are included in the page’s header:

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

In addition, the mc:Ignorable="d" attribute must be set for the page. Now, it is possible to add the d:DataContext attribute to the page. But how to specify a new instance of some Viewmodel class as content of this attribute? Here another component from the d namespace comes into play: d:DesignInstance allows to create an instance of some class, pass it to the containing object – and make sure that this happens only at design-time, not when the application is actually running!

Here comes an example of the full page that can replace the code fragment presented at the beginning of this article:

<views:BaseView
    x:Class="MyPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MVVMbasicsTestTablet"
    xmlns:views="using:MVVMbasicsTabletExtensions.Views"
	xmlns:viewmodels="using:MyApp.Viewmodels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
	d:DataContext="{d:DesignInstance viewmodels:MyViewmodel}">

	<!-- insert page content here-->
	
</views:BaseView>

The best is: This works for all three platforms (Windows Store, Windows Phone, and WPF Desktop), and I’d strongly recommend to use this pattern on all platforms you’re developing for, since it helps to avoid both functional and performance-related issues, as stated above!

Permanent link to this article: http://www.mobilemotion.eu/?p=932&lang=en

Older posts «