Solved

How to define DataContext in XAML using StaticResource

Posted on 2010-08-19
5
5,535 Views
Last Modified: 2013-12-17
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

0
Comment
Question by:esc_toe_account
  • 3
  • 2
5 Comments
 
LVL 27

Expert Comment

by:MikeToole
ID: 33482610
>>            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}"  >

0
 

Author Comment

by:esc_toe_account
ID: 33488707
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)
0
 

Author Comment

by:esc_toe_account
ID: 33488744
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

0
 
LVL 27

Accepted Solution

by:
MikeToole earned 500 total points
ID: 33490835
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

0
 

Author Comment

by:esc_toe_account
ID: 33500838
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.

0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now