Setting Datacontext in Xaml in Wpf

Setting DataContext in XAML in WPF

This code will always fail.

As written, it says: "Look for a property named "Employee" on my DataContext property, and set it to the DataContext property". Clearly that isn't right.

To get your code to work, as is, change your window declaration to:

<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleApplication"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:Employee/>
</Window.DataContext>

This declares a new XAML namespace (local) and sets the DataContext to an instance of the Employee class. This will cause your bindings to display the default data (from your constructor).

However, it is highly unlikely this is actually what you want. Instead, you should have a new class (call it MainViewModel) with an Employee property that you then bind to, like this:

public class MainViewModel
{
public Employee MyEmployee { get; set; } //In reality this should utilize INotifyPropertyChanged!
}

Now your XAML becomes:

<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleApplication"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
...
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" Text="{Binding MyEmployee.EmpID}" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" Text="{Binding MyEmployee.EmpName}" />

Now you can add other properties (of other types, names), etc. For more information, see Implementing the Model-View-ViewModel Pattern

Setting DataContext in XAML C# WPF

It appears that you cant bind a DataContext to a field, it has to be a property. Changing cueSheet to a property allowed me to bind it as the DataContext of my TextBox and DataGrid.

While

DataContext="{Binding cueSheet}"

didn't work because it was just a field, changing it to a property worked

DataContext="{Binding CueSheet}"

and I no longer need txtCueFilePath.DataContext = cueSheet; and dgCueTracks.DataContext = cueSheet; in the code-behind.

WPF DataContext in XAML, why and what's the correct approach

You should not explicitly set the DataContext of UserControls at all, neither in XAML nor in code behind.

UserControls are supposed to inherit the value of their DataContext property from their parent element, and have their properties bound to properties of the object in the inherited DataContext.

This typically looks like

<Window ...>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
...
<local:MyUserControl MyProperty="{Binding VmProperty}" .../>
</Window>

where VmProperty is a property of MainViewModel. If the main view model provides a sub view model with properties that are meant to be displayed by the UserControl, the Binding may look like

<local:MyUserControl MyProperty="{Binding SubViewModel.SubVmProperty}" .../>

Those Bindings won't work when the UserControl had explicity set its own DataContext.


Alternatively, the elements in the XAML of the UserControl may also directly bind to the properties of the DataContext object, like

<UserControl x:Class="MyNamespace.MyUserControl" ...>
...
<TextBlock Text="{Binding SubVmProperty}"/>
...
</UserControl>

where you would instantiate the control like

<local:MyUserControl DataContext="{Binding SubViewModel}"/>

If the UserControl had set its own DataContext, the above Binding would fail as well.


A UserControl is often instatiated by a DataTemplate like

<DataTemplate DataType="{x:Type local:SubViewModel}">
<local:MyUserControl/>
</DataTemplate>

where the DataContext is automatically assigned the object to which the DataTemplate is applied. This would also also fail to work if the UserControl had explicity set its own DataContext.

How to do this.DataContext = this: in XAML....for eg Window.DataContext local:MainWindow/ /Window.DataContext --

This sets the DataContext to a new instance of MainWindow (which will in turn set the DataContext to a new instance and so on):

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

The equivalent of this.DataContext = this would be: <Window ... DataContext="{Binding RelativeSource={RelativeSource Self}}">.

You may also set the design time DataContext:

d:DataContext="{d:DesignInstance Type=local:MainWindow, IsDesignTimeCreatable=True}

Correctly setting my DataContext in XAML

Trying changing your

<CollectionViewSource x:Key="cvsStudentList" Source="{StaticResource StudentList}" Filter="CollectionViewSource_Filter"/>

to

<CollectionViewSource x:Key="cvsStudentList" Source="{Binding StudentList}" Filter="CollectionViewSource_Filter"/>

You're correct that your DataContext is set initially to an instance of OCLMEditorModel when the window is instantiated. That should mean that your CollectionViewSource resource should be able to grab the StudentList property from the Window's DataContext through a direct binding.

Yes, what you're doing in your xaml is binding your DataGrid's ItemsSource to a distinct instance of the CollectionViewSource. However, you're also binding that CollectionViewSource instance to a distinct instance of a StudentList defined in your Window.Resources ( <local:StudentList x:Key="StudentList" />
), which I don't think is what you want. The change I suggested above will make your CollectionViewSource bind to the OCLMEditorModel's StudentList property instead.

Set DataContext in WPF XAML to a specific object

Yes, this is possible: Just assign the DataContext from your constructor

class MainWindow : Window
{
public MainWindow(ViewModelClass viewmodel)
{
InitializeComponent();
this.DataContext = viewmodel; // should work before as well as after InitalizeComponent();
}
}

Binding it from the XAML obviously does not work, for some reason.

Setting WPF datacontext for a specific control

Instead of changing the DataContext of your window, you should add a property to your MyBusinessObject class like this one:

private Widget _selectedWidget;
public Widget SelectedWidget
{
get { return _selectedWidget; }
set
{
if (_selectedWidget == value)
{
return;
}

_selectedWidget = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedWidget"));
}
}

Then bind SelectedWidget to the SelectedItem property of your combobox. Anywhere that you need to use the widget's properties you can do this:

<TextBox Text="{Binding Path=SelectedWidget.WidgetColor}"></TextBox>


Related Topics



Leave a reply



Submit