How to define DataContext in XAML using StaticResource

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# commented out code below) but want to learn how to do it in XAML. I have tried all of the examples I can find (including one on this site) 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?
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>

Open in new window

esc_toe_accountAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

MikeTooleCommented:
>>            bModel1 bNorthWind = new bModel1();
>>            //this.DataContext = bNorthWind;

Why the introduction of a new class, bModel1?

The equivalent in XAML of     //this.DataContext = bNorthWind;    is a resource entry plus a DataContext assignment:

-   This statement essentially creates an instance of bNorthWind with TheViewModel as the key.

    <vm:bNorthWind  x:Key="TheViewModel" />

-   To set a DataContext from it assign it on an element in your xaml:

     DataContext="{StaticResource TheViewModel}"

The assignment in code-behind sets the context for the whole Window. To get a near-equivalent scope you could set the context on the Grid:

<Grid      DataContext="{StaticResource TheViewModel}"  >

esc_toe_accountAuthor Commented:
Thanks for your suggestion. That was one of the variants I tried earlier and did not have success with.

Here are the two compile errors I get with the code you sugested:

Error      1      The tag 'bNorthWind' does not exist in XML namespace 'clr-namespace:DataGridEF'. Line 8 Position 10.      C:\VS\Samples\DataGridEF\DataGridEF\MainWindow.xaml      8      10      DataGridEF

Error      2      The type 'vm:bNorthWind' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.      C:\VS\Samples\DataGridEF\DataGridEF\MainWindow.xaml      8      10      DataGridEF

Not sure why it can't find bNorthWind. I tried declaring it public but that didn't make any difference.

In answer to your question 'why the new class bModel' - that is because I am prototyping a MVVM pattern and have separated out the View from the ViewModel (or Business Model: bModel)
esc_toe_accountAuthor Commented:
I can't edit the original submission so here is what the new public declaration of bNorthWind looks like. But as mentioned above, didn't make the object viewable - still get the errors shown.

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

        private void SaveBtn_Click(object sender, RoutedEventArgs e)
        {

            bNorthWind.SaveChanges();
        }
    }

Open in new window

MikeTooleCommented:
When setting the DataContext in XAML there is no need for any code in the code behind.
This entry in the resources section creates a new instance of bNorthWind:
    <vm:bNorthWind  x:Key="TheViewModel" />
... but this assumes that bNorthWind is a class, your code suggests that it's actually an instance of bModel1

In the MVVM pattern the Model and ViewModel are different classes

The attached example shows a class set as datacontext
- the code behind file is completly empty

<Window x:Class="cSharpTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:cSharpTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <vm:MyData x:Key="ViewModel"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource ViewModel}">
        <ListBox Name="MyListBox" ItemsSource="{Binding Primes}"/>
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cSharpTest
{
    class MyData
    {
        public MyData()
        {
            _primes = new int[5] { 1, 3, 5, 7, 11 };
        }
        private int[] _primes;
        public  int[] Primes
        {
            get { return this._primes; }
         }
    }
}

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
esc_toe_accountAuthor Commented:
Thanks Mike, your comments got it working for me. I did not realize that
    <vm:bModel1 x:Key="TheViewModel" />
was actually creating a new instance; I was expecting it to reference an existing instance! Therefore, by simply putting some code in the class constructor to fetch the data I got the datagrid to display the customer table.

I don't think I will be using this construct very much: Visual Studio designer reports it can't create the instance (I assume because the data base connection is not open) however the code runs fine.

Apparently, in order to reference an existing instance (created in C#) I would have to use a BindableStaticResource which is way more work than I want to get into, especially since a single line of C# (this.DataContext = bNorthWind;) sets the DataContext quite easily.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.