Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access DataContext instance in code when set in XAML

Tags:

c#

mvvm

wpf

I usually instantiate my ViewModel in codebehind and set it as the DataContext for the Window or UserControl.

For this simple ViewModel:

public class ViewModel
{
    public ObservableCollection<string> items { get; set; }

    public ViewModel()
    {
        items = new ObservableCollection<string>();
        items.Add("FirstItem");
        items.Add("SecondItem");
        items.Add("ThirdItem");
    }
}

i am adding my local namespace and the following syntax will set the things right:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

Fine, i understand that a ViewModel object is instantiated and set as DataContext for the window, it works as expected but is there any way to access the instantiated object from code?

If i create the object in the codebehind with

ViewModel vm = new VewModel();
this.DataContext = vm;

i am able to access vm instance but with the XAML approach, how can it be reached?

I've created this small example in order to find out if there is a simple answer available.

like image 936
Olaru Mircea Avatar asked Jun 22 '15 08:06

Olaru Mircea


People also ask

How to use DataContext in WPF?

User interface elements in WPF have a DataContext dependency property. That property has the aforementioned "value inheritance" feature enabled, so if you set the DataContext on an element to a Student object, the DataContext property on all of its logical descendant elements will reference that Student object too.

How to set DataContext for User control in WPF?

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 .


1 Answers

When you set the DataContext of any element, then all of the children of said element will also have the same DataContext.

Picture the scene:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

Here you have given the Window a DataContext. Now, all child elements within your window effectively have the same DataContext.

<TextBox Text="{Binding MyProperty}" />

To get hold of the DataContext in code-behind, you can simply reference the DataContext of the element.

ViewModel vm = (ViewModel)this.DataContext;

The code above references the DataContext of the Window.

If you need to be more specific, and get the DataContext of a specific element, then you can simply reference the element by name.

ViewModel vm = (ViewModel)elementName.DataContext;

All that aside, you should never set the DataContext in code-behind. The MVVM design pattern likes to keep things separated, and if you start setting the DataContext of a UserControl for example, then things get screwed up pretty quickly.

Setting the DataContext in XAML is the right way to go.

like image 171
Mike Eason Avatar answered Sep 23 '22 07:09

Mike Eason