16

Originally my .xaml form used the following line to set the Designer's DataContext where the view model was a non-generic type (note I'm talking about the Design time DataContext not the actual DataContext that will be used at runtime).

<Window ...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
d:DataContext="{d:DesignInstance Dialogs:CustomerSearchDlogViewModel}"
...>

Now instead of CustomerSearchDlogViewModel I have a generic SearchDialogViewModel but I can't figure out what syntax will work in the <Window> tag to let me specify that view model.

Tod
  • 8,192
  • 5
  • 52
  • 93

2 Answers2

26

That is not possible unless the markup extension (DesignInstance) provides properties to pass type arguments, which i doubt. So you might want to subclass as suggested or write your own markup extension which creates generic instances (in fact that is what i am doing right now).

Edit: This extension should do it:

public class GenericObjectFactoryExtension : MarkupExtension
{
    public Type Type { get; set; }
    public Type T { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var genericType = Type.MakeGenericType(T);
        return Activator.CreateInstance(genericType);
    }
}

Initially i had some problems getting the object type from a type-name but you can let the XAML parser resolve the type for you which is neat:

DataContext="{me:GenericObjectFactory Type={x:Type Dialogs:CustomerSearchDlogViewModel`1},
                                      T=Data:Customer}"

(Note the `1 at the end to reference a generic type. If you drop the x:Type wrapping the backtick will cause an error.)

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • I don't know how to do the latter so if you do it and write a blog or anything that might help I would be an avid reader. – Tod Nov 23 '11 at 00:02
  • @Tod: It's a major pain, it requires a lot of reflection and i am a bit stuck, if anything comes from it i'll edit my answer and tell you. – H.B. Nov 23 '11 at 00:03
  • @Tod: I think i found a way after all. – H.B. Nov 23 '11 at 00:46
  • @H.B. I came up with a similar solution myself, however IntelliSense does not seem to work with this. Do you know if it’s possible to adjust this further so that VS2013’ IntelliSense gives you completion in bindings? – poke Mar 10 '14 at 14:44
  • @poke: Sorry, can't help you with that, don't even have it installed anywhere right now... – H.B. Mar 10 '14 at 17:46
  • @H.B. Ah well, too bad; guess I’ll just have to live with it. Thanks anyway :) – poke Mar 10 '14 at 17:47
  • I guess as of today `d:DataContext="{d:DesignInstance {x:Type local:SampleVM'1}}"` works. (Replace the ' with a ` , it messes with the markup here) – FredM Aug 12 '22 at 09:09
4

A clean option would be to create a new type which just flattens the generic type:

public class CustomerSearchDialogViewModel : SearchDialogViewModel<Customer> 
{
}
devdigital
  • 34,151
  • 9
  • 98
  • 120
  • Since I already have a CustomerSearchDialogViewModel it will be nice and simple to wipe out its content and redefine it like you suggest (instead of deleting it). I didn't think of this plus it's always good to find out what can't be done. – Tod Nov 23 '11 at 00:03