Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting user control based on type of DataContext

Tags:

wpf

xaml

I'm trying to build a set of typical CRUD maintenance forms in WPF - that are going to be pretty much the same except that they work on different database records.

Rather than creating a new window class for each, I'm trying to use a single window class that instantiated with a different ViewModel class for each database table, and for which I have a different UserControl defined for each ViewModel.

So, if I instantiate the window with its DataContext set to an instance of Record1ViewModel, I want to display it in the window using a Record1UserControl, if it's set to an instance of Record2ViewModel, I want to display it using a Record2UserControl.

I've verified that both user controls work fine, by defining them each directly in the window's XAML. But I've not figured out how to select one or the other, based on the type of the ViewModel.

This is not working:

<myWindow.Resources>

    <DataTemplate x:Key="{x:Type ViewModels:Record1ViewModel}">
        <MaintenanceControls:Record1 />
    </DataTemplate>
    <DataTemplate x:Key="{x:Type ViewModels:Record2ViewModel}">
        <MaintenanceControls:Record1 />
    </DataTemplate>

</myWindow.Resources>

<ContentPresenter Content="{Binding}" />

What I get, in the ContentPresenter, is the name of the type. The DataTemplates are not used.

Any ideas?

like image 687
Jeff Dege Avatar asked Dec 29 '11 23:12

Jeff Dege


People also ask

Should DataContext be set to self at usercontrol element level?

This is a summary of the above link. DataContext should not be set to Self at UserControl Element level. This is because it breaks the Inheritance of the DataContext. If you do set it to self and you place this control on a Window or another control, it will not inherit the Windows DataContext.

How do I bind a DataContext to a usercontrol?

By setting the UserControl DataContext to itself, this overwrites the DataContext and breaks Inheritance. Instead, nest it one Element deep in the XAML, in your case, the StackPanel. Put the DataContext binding here and bind it to the UserControl. This preserves the Inheritance.

When is a control not a usercontrol?

If the control is depending on some VM or is tightly coupled / depends on being placed into a specific context to work then it isn't a "control". You've violated the separation of concerns principle. As far as I can tell, this breaks any UserControl with a DependencyProperty. See nikolalukovic.com/programming/… and/or the answer by @jdawiz.

How to populate a DataContext from a mainviewmodel?

You usually start with a MainViewModel and assign that to your windows DataContext. From there you just populate everything. Sorry, something went wrong. This approach is called "state tree".


1 Answers

You can use the DataTemplateSelector to dynamically select a DataTemplate at run time something along the lines of

public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;

                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
like image 198
parapura rajkumar Avatar answered Sep 27 '22 19:09

parapura rajkumar