I've been merrily using the DesignData in Windows Phone apps, and I was hoping to use it to help visualise designs in a Metro style app in VS2012/Blend for VS.
I've tried the hopefully obvious:
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="MyRootNamespace.Views.EventView"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyRootNamespace.Views"
xmlns:common="using:MyRootNamespace.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:bm="using:Bing.Maps"
d:DataContext="{d:DesignData Source=../SampleData/SpecialEventSampleData.xaml}"
mc:Ignorable="d">
With the SpecialEventSampleData.xaml looking loosely like:
<local:SpecialEvent
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyRootNamespace.ViewModels"
EventName="Foo Fighters"
Description="This exclusive April Fools Gig will see Dave Grohl and the rest of the Foo Fighters rock out at this exclusive made up gig"
VenueName="Village Hall"
/>
The class to which it refers has a public, parameterless constructor, but Visual Studio is giving an error:
Error Cannot create an instance of "SpecialEvent". C:...\MyRootNamespace.Windows\SampleData\SpecialEventSampleData.xaml
In addition, I was expecting to have to set the build action to "DesignData", or similar, but this doesn't appear to be an option in Visual Studio 2012?
What do I need to do to be able to get design time data to work in VS2012/Blend?
Is SpecialEvent your ViewModel? If so, can you do something like this in your XAML (directly after your common:LayoutAwarePage opening declaration)?
<d:Page.DataContext>
<local:SpecialEvent>
</d:Page.DataContext>
And then remove this line from your common:LayoutAwarePage:
d:DataContext="{d:DesignData Source=../SampleData/SpecialEventSampleData.xaml}"
I have code similar to this that is working.
In Windows Phone (I believe) the path to the sample data file is relative to the application root. In Windows 8, the path to the sample data file is relative to the page xaml file you want to use it in.
In your sample above, the page.xaml file would need to be in a sub-folder of the project but in a different folder than SampleData.
Windows 8 sample data does not automatically create collection instances for you. So, if you have sample data like this:
<Event>
<Attendees>
<Attendee Name="Joe" />
</Attendees>
</Event>
you would need to make sure that the backing field for the Attendees property is set to a new collection instance when you define the variable. If you are using automatic properties (Attendees { get; set; } syntax) you will need to set the property to a new collection instance in the constructor before items can be added in xaml.
Finaly, Windows 8 xaml cannot handle generic types. So, if your Attendees property is of type Collection<Attendee> you will not be able to create an instance of it in xaml.
You can always make a simple class called AttendeeCollection that inherits from Collection<Attendee> and create instances of that in your xaml instead.
Hope that helps.
Try full path to the xaml file instead of relative.
This is a touch obscure, but it boils down to the implementation I had of INotifyPropertyChanged
on my View-Model.
In my Windows Phone code, I have to go to a small amount of effort to ensure that the events raised by background worker threads pop out on the UI thread:
protected delegate void OnUIThreadDelegate();
protected void OnUIThread(OnUIThreadDelegate onUIThreadDelegate)
{
if (Deployment.Current.Dispatcher.CheckAccess())
{
onUIThreadDelegate();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(onUIThreadDelegate);
}
}
This was then used:
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
OnUIThread(() =>
{
base.OnPropertyChanged(e);
});
}
It appears that when porting that code, I was not checking the result of CoreWindow.GetForCurrentThread()
which was causing an exception to fire deep in the darkest depths of the code, as the designer was setting the properties on my type, and I was trying to raise the events and dying horribly instead. My bad.