30

How can I set the DataContext on my Grid in XAML, instead of in the constructor?

Here is how I do it in the constructor (LayoutRoot is the XAML Grid defined in the XAML):

this.LayoutRoot.DataContext = this.HPVM;

I would prefer to do it right in the XAML, but I do not know how to reference the HPVM object in XAML. HPVM is a public property on the USerControl class.

It works fine as listed above, but again, I just want to know how to properties of the UserControl class in XAML, rather than always having to do it in code.

Here is all the relevant code:

  <UserControl x:Class="SilverlightApplication1.SLHolePattern" x:Name="HolePatternsControl"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib"    
    xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
    xmlns:local="clr-namespace:SilverlightApplication1"    
    xmlns:GeoPatterns="clr-namespace:GeoPatterns"
    Height="700">


    <UserControl.Resources>
    ...

And here is my constructor where the DataContext is currently set:

namespace SilverlightApplication1
{
    public partial class SLHolePattern : UserControl, INotifyPropertyChanged
    {
        public HolePatternsViewModel HPVM;

        public SLHolePattern()
        {
            InitializeComponent();

            this.HPVM=new HolePatternsViewModel();
            this.LayoutRoot.DataContext = this.HPVM;
            ...more code here
        }

It all works fine, but I just want to learn how to set the DataContext in XAML, not in code.

MattSlay
  • 9,115
  • 5
  • 43
  • 52

7 Answers7

23

The answer Chris gave works just fine. I have tested and it worked for me. You can instantiate your class in XAML (within the UserControl.Resources) and then bind the datacontext to a static resource.

Follow code:


<UserControl ...>
    <UserControl.Resources>
       <myNS:MyClass x:Name="TheContext" x:Key="TheContext"></myNS:MyClass>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource TheContext}" >
        <TextBlock Text="{Binding Path=Field1}">
        </TextBlock>
    </Grid>
</UserControl>

Klinger
  • 4,900
  • 1
  • 30
  • 35
  • If I instantiate the ViewModel class in XAML, can I still reference in the code-behind constructor? The reason I ask is that I presently set some values on the ViewModel in the constructor before the form is shown the user. – MattSlay Mar 04 '09 at 17:24
  • 3
    Yes, you can. You can do as follow: var aCustomer = this.Resources["Cust"] as Customer; aCustomer.Name = "abc"; – Klinger Mar 04 '09 at 20:56
  • 2
    I forgot to add a x:Name attribute. x:Key works within XAML and x:Name makes the object visible to code. – Klinger Mar 04 '09 at 22:42
  • 1
    Yes, it does work, but *creates* the object in XAML. It still does not address accessing constructor-created object instances from XAML. Best I can tell it cannot be done. You must set DataContext from code if object is created in code. – MattSlay Mar 05 '09 at 15:44
  • I agree with you, it cannot be done. There is no syntax to support that. – Klinger Mar 05 '09 at 16:21
  • Instantiating object in XAML works if you are ok in using the Resources[".."] way. Using x:Name to expose the resource will not work (null reference) because the autogenerated class does not retrieves the object correctly (IMO). See my post here: http://silverlight.net/forums/t/77509.aspx – Klinger Mar 05 '09 at 16:25
10

The following monstrosity works in Silverlight 4

<UserControl 
  DataContext="{Binding HPVM, RelativeSource={RelativeSource Self}}">
Chui Tey
  • 5,436
  • 2
  • 35
  • 44
6
<UserControl.DataContext>
  <vm:ThisUCViewModel />
</UserControl.DataContext>
someguy
  • 61
  • 1
  • 1
2

try something like this.....

<Grid DataContext="{Binding Path=HPVM}">
</Grid>

where HPVM is a public member of this--> your form etc.

Create the instance of your class in the xaml, by adding something like this to your resources section.... (don't forget to add your xmlns namespace)

<my:bogart x:Key="franken"/>

then, bind the data context to the static resource you just added....

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource franken}">
    <TextBox  Background="Red" Foreground="White" Text="{Binding Path=sum}"  />
</Grid>
Muad'Dib
  • 28,542
  • 5
  • 55
  • 68
  • Doesn't work. There needs to be a path somehow that says where HPVM is. in the code method, that what the "this." part does. HPVM is a property on the class. I cannot figure out the right way to reference the instantiated class to get to HPVM. – MattSlay Mar 03 '09 at 16:15
  • The second code example does work, but *creates* the object in XAML. It still does not address accessing constructor-created object instances from XAML. Best I can tell it cannot be done. You must set DataContext from code if object is created in code. – MattSlay Mar 05 '09 at 15:43
1

In Silverlight 4, I was able to get this working by doing the following:

Give the Page/UserControl an x:Name="myPage"

In your control binding use normal Element bidning syntax. In my case I want to bind to an observable collection of objects in my code behind for my ItemsSource property:

<ComboBox 
    ItemsSource={Binding ElementName=myPage, Path=MyObservableObjectList, Mode=TwoWay}

I haven't tried this with DataContext but know you can do element to element binding for DataContext as I do this for Grids whose context is based on the selected item of some other drop down on the page.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Doug
  • 11
  • 1
0

This is not possible (It is possible in WPF with {Binding RelativeSource={RelativeSource Self}}, but Silverlight is more limited.

You have to do it through code.

biju
  • 17,554
  • 10
  • 59
  • 95
Srdjan Jovcic
  • 784
  • 4
  • 9
0
<UserControl.Resources>
  <ResourceDictionary>
     <vm:YourModelx:Key="myModel"/>
  </ResourceDictionary>
</UserControl.Resources>
<UserControl.DataContext>
   <Binding Source="{StaticResource myModel}"/>
</UserControl.DataContext>
Jacfay
  • 1