views:

7769

answers:

4

Hi. I'm trying to make a simple crossword puzzle game in Silverlight 2.0. I'm working on a UserControl-ish component that represents a square in the puzzle. I'm having trouble with binding up my UserControl's properties with its' elements. I've finally (sort of) got it working (may be helpful to some - it took me a few long hours), but wanted to make it more 'elegant'.

I've imagined it should have a compartment for the content and a label (in the upper right corner) that optionally contains its' number. The content control probably be a TextBox, while label control could be a TextBlock. So I created a UserControl with this basic structure (the values are hardcoded at this stage):

    <UserControl x:Class="XWord.Square"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    FontSize="30" 
    Width="100" Height="100">
        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
                Text="7"/>
            <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0"  
                Text="A"
                BorderThickness="0" />

        </Grid>
    </UserControl>

I've also created DependencyProperties in the Square class like this:

     public static readonly DependencyProperty LabelTextProperty;
     public static readonly DependencyProperty ContentCharacterProperty;

     // ...(static constructor with property registration, .NET properties
     // omitted for brevity)...

Now I'd like to figure out how to bind the Label and Content element to the two properties. I do it like this (in the code-behind file):

     Label.SetBinding( TextBlock.TextProperty, new Binding { Source = this, Path = new PropertyPath( "LabelText" ), Mode = BindingMode.OneWay } );
     Content.SetBinding( TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath( "ContentCharacter" ), Mode = BindingMode.TwoWay } );

That would be more elegant done in XAML. Does anyone know how that's done?

A: 

I may not be understanding your issue exactly. In Silverlight, you are able to bind to almost any data object. So, if you have a PuzzleSquare class that contains properties Content and Label, you may bind to these properties directly from the object.

Let's say you created a simple object PuzzleSquare:

    public class PuzzleSquare
    {
      public string Content{ get; set; }
      public string Label{ get; set; }

      public void PuzzleSquare(){};
      public void PuzzleSquare(string label, string content):this()
      {
         Content = content;
         Label = label;
      }    
    }

So, if you are building the app with the classic view/code behind model, your code behind would add this object to the DataContext property of the grid on page load:

LayoutRoot.DataContext = new PuzzleSquare("1", "A");

Your Xaml would bind to the Square property:

    <TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding Label}"/>            
    <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding Content}" BorderThickness="0" />

Does that make sense?

ib.

Ireney Berezniak
That makes sense, but my scenario is different. In your case PuzzleSquare and the UI are seperate classes. I'm not that far yet. I'm still defining my UI class. I want to add a public property to my UI class what binds to a sub-element property. Then I'll bind the data to the public prop of the UI.
ghostskunks
Ran out of chars there.. So in my design, I'll be using my class like so<s:SomeCustPnl DataContext={StaticResource someDataInstance}><DataTemplate><s:Square Content="{Binding contentProp}"/>..However, I need to wire up the Content property to a subelement of Square. Does that make sense?
ghostskunks
+1  A: 

I think you are looking for UI Element to Element Binding which is a feature of Silverlight 3.

Robert Kozak
+6  A: 

First, set the DataContext on the UserControl using {RelativeSource Self}:

<UserControl x:Class="XWord.Square"  
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
FontSize="30"   
Width="100" Height="100" 
DataContext="{Binding RelativeSource={RelativeSource Self}}">

Now you can bind the individual elements to the properties of the usercontrol:

<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding LabelText}"/>  
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding ContentCharacter}" BorderThickness="0" />

For SL 2.0, you'll need to set the DataContext on the UserControl's Loaded event handler.

private void UserControl_Loaded( object sender, RoutedEventArgs e ) {
    LayoutRoot.DataContext = this;
}
Schemer
A: 

This worked in Silverlight 4.0

Put a name on the UserControl, and then refer to it in the TextBlock

 <UserControl x:Class="XWord.Square"
    ...omitted for brevity ...
    x:Name="Square">

        <TextBlock x:Name="Label" ...
            Text="{Binding Path=LabelText,ElementName=Square}"/>
Chui Tey
This breaks if you consume the UserControl in the application and give it a name.
James Cadd