Windows Store App Design-time DataContext

2020-03-08 08:13发布

问题:

I've been a XAML developer for years now but this one has stumped me. I've been sleeping badly so maybe I'm being dense.

Just orientating myself with Windows Store apps, I noticed that the LayoutAwarePage has a DefaultViewModel these days, which is nice but I it gets set only at runtime. Really, we need a DataContext established during design time to see real fake data.

So after failing with some more convoluted ViewModel hook-up code, I am down to this and it doesn't work:

public sealed partial class TemplatePage : LayoutAwarePage
{
    public TemplatePage()
        : base()
    {
        this.DefaultViewModel = new ObservableDictionary<string, object>();
        this.DefaultViewModel.Add("Name", "Design-time value.");

        this.InitializeComponent();
    }

...}

Both VS2012 and Blend do not see the DataContext at all. When I click Create Data Binding for a TextBlock, Blend reports

The data context is not set. You can enter a Path when Custom is checked.

This works at runtime and my convoluted smart-ass stuff also works, but not in the designer. Has the way this all works changed now?? Did I miss the memo?

Update

So using guidance from a tutorial on Channel9

http://channel9.msdn.com/Series/Windows-Store-apps-for-Absolute-Beginners-with-C-/Part-8-Understanding-how-Data-Binding-Works-at-Design-Time

I am at least now able to include more code that doesn't work.

I've created a couple of fake data sources in the shape of classes extending BindableBase, much like how the tutorial has this setup, but the XAML side of things is weird.

The XAML says, at the Page element level, construct a DesignTimeDataHub object and use this as the DataContext. Then, at the root Grid level, use reset the DataContext to the CommonFakeData property.

The Blend Create Data Binding dialog for the TextBlock under the Grid seems to think that the DataContext is what's set at the Page level!

Whether I use {Binding CommonFakeData.Title} or {Binding Title} it doesn't work.

I'm clearly screwing this all up. I'm glad they made this harder since writing code has always been too easy.

回答1:

Okay, I've cracked it. The format for setting the DataContext should be:

d:DataContext="{Binding PropertyNameOfSubViewModel, Source={d:DesignInstance Type=myNamespace:ViewModelTypeName, IsDesignTimeCreatable=True}}"

I now leave the Page level DC as the DefaultViewModel. I then add another DC attribute to the layout root Grid element with the above correct DC design-time syntax.

The TextBlock then needs only the name of a property on the SubViewModel in its binding. So the fake data view models are roughyl like this:

public class DesignTimeDataHub : BindableBase // Probably doesn't need to be BindableBase.
{
    public CommonBindableFakeData CommonFakeData { // get set }
}

public class CommonBindableFakeData : BindableBase
{
    ctor { // set some default fake values }

    public string Title { // get set }
}

Here's what it looks like: