7

I want to declare a DataContext through a static resource in XAML as a binding for the Customers in the Northwind database. I can do this easily in code (C#) but want to learn how to do in XAML. I have tried all of the examples I can find but none of them work for me. I believe the issue is in the two XAML lines of code I have labeled [Option1] and [Option2]. Can you clarify what the syntax for this really should be?

C#

namespace DataGridEF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            bModel1 bNorthWind = new bModel1();
            //this.DataContext = bNorthWind;
            bNorthWind.GetCustomers();
        }
    }
}

namespace DataGridEF
{
    public class bModel1
    {
        List<Customer> _Customers;
        public List<Customer> Customers
        {
            get { return _Customers; }
            set { _Customers = value; }
        }

        public void GetCustomers()
        {
            NorthwindEntities NorthWind = new NorthwindEntities();
            var CustomerQ = from cust in NorthWind.Customers select cust;
            _Customers = CustomerQ.ToList();
        }

    }
}

XAML

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

<Window.Resources>
    <vm:bModel1 x:Key="TheViewModel" />
</Window.Resources>

<Grid>
    <DataGrid AutoGenerateColumns="False" Height="195" 
              HorizontalAlignment="Left" Margin="20,89,0,0" 
              Name="dataGrid1" ItemsSource="{Binding Path=Customers}" 
              [option1]DataContext="{StaticResource TheViewModel}"
              [option2]DataContext=
                  "{Binding Path=., Source={StaticResource TheViewModel}}"
              VerticalAlignment="Top" Width="471" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Path=ContactName}" />
            <DataGridTextColumn Header="Address" Binding="{Binding Path=Address}" />
            <DataGridTextColumn Header="City" Binding="{Binding Path=City}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>
</Window>
1
  • Once you've set the Window.DataContext in XAML (<Window.DataContext><vm:bModel1 /></Window.DataContext>) you shouldn't have to set the DataContext on the data grid at all. Commented Dec 4, 2019 at 23:43

3 Answers 3

9

If to avoid complicating the question with Entities Framework and MSSQL NorthWind database, then the good illustration is provided in Example2 sample code of codeproject "WPF/MVVM Quick Start Tutorial"

For your XAML you should change the beginning of it to:

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

<Window.DataContext>
        <vm:bNorthWind />
    </Window.DataContext>
<Grid>
<!---Couldnt check your code due to dependencies on 
     EF and MSSQL NorthWind database

     See the reference for working illustration sample:
 http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

-->
</Grid>
</Window>

Another variation of this approach can be seen in "What is the advantage of setting DataContext in code instead of XAML?", the part:

    <StackPanel.DataContext>
        <local:CustomerViewModel />
    </StackPanel.DataContext>   

Migrating DataContext definition from codebehind to XAML is unrelated to the usage of either StaticResource or DynamicResource. See: What's the difference between StaticResource and DynamicResource in WPF? probably better addressed in codeproject WPF: StaticResource vs. DynamicResource

Related, helpful and further reading:

Sign up to request clarification or add additional context in comments.

Comments

1

I prefer to set the key as a static string - WPF has enough magic strings without cornering yourself into a refactoring corner if you can easily avoid it.

in App.xaml

xmlns:viewModels="clr-namespace:MyAppNamespace.ViewModels"
xmlns:local="clr-namespace:tvCADdesktop"
x:Name="App"
...
<viewModels:ApplicationViewModel x:Key= "{x:Static local:App.MainVmResourceKey}"/>

in App.xaml.cs

public static readonly string MainVmResourceKey = "MainVm";

in my various Control.xaml

<UserControl.DataContext>
    <Binding>
        <Binding.Source>
            <StaticResource ResourceKey="{x:Static app:App.MainVmResourceKey}" />
        </Binding.Source>
    </Binding>
</UserControl.DataContext>

note the UserControl part is whatever type you want to apply the ViewModel to.

Comments

1
<Window xmlns:vm="clr-namespace:YourApplication.ViewModels">

    <Window.Resources>
        <vm:MainWindowViewModel x:Key="MWVM" />
    </Window.Resources>

    <Window.DataContext>
        <StaticResource ResourceKey="MWVM" />
    </Window.DataContext>

</Window>

Edit:

Unlike the other answers, this one attempts to simply show you exactly how to define a ViewModel as a StaticResource in XAML and use that resource for a DataContext.

4 Comments

Is there any benefit to using a static resource vs. setting Window.DataContext directly? If not, then this answer suggests setting it directly.
@ZevSpitz - Yes, there is a benefit when you are binding a property from your main ViewModel (DataContext of Window), for example, to a UserControl that has its own ViewModel. If you try to bind a property from the main ViewModel to the UserControl in XAML it won't work and you'll even get a warning. So what you have to do is reference the main ViewModel. Like this: <controls:MyUserControl Title="{Binding Path=Title, Source={StaticResource ResourceKey=MWVM}}" />
Not enough of a justification to my mind. If you need to worry about that case, you can use {Binding Path=DataContext.Title, RelativeSource={RelativeSource AncestorType=Window}}.
@ZevSpitz That certainly works too. It just requires longer bindings and gives less flexibility, if you need that sort of thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.