Reputation: 192427
I cannot understand the Silverlight documentation on data binding. I seek a very simple example.
Suppose I define a UserControl in a XAML file. The toplevel child of the UserControl is a Grid, of n columns and m rows. Within the Grid is a Rectangle. Like this:
<UserControl....
<Grid ...>
<Rectangle ...>
The rectangle should be displayed in a particular (row, column) within the Grid. This row/column pair changes at runtime, according to various evevnts.
I think I can use data binding for that. Can someone confirm this is a reasonable use of data binding?
I think I can do something like this:
<Rectangle x:Name="rect"
Grid.Column = "{Binding ???}"
Grid.Row = "{Binding ???}" />
BUT, I don't know what to put for the binding.
What goes there? And, How do I validate what I put there? It seems I can put any string I like, even the full text of the Declaration of Independence, and it behaves exactly the same way. Which is to day, it does nothing. It does not work. It does not throw an exception.
I don't know what that string should be. and I don't know how to debug what I put there. There seems to be no way to know if it is correct or valid or ridiculous.
A simple example is all it would take. I don't know why the MSDN doc is so obtuse. Am I thoe only one who cannot understand things like this
In Silverlight, you can bind to the target value of any dependency property. The source property value for a data binding need not be a dependency property; it can be a property on a CLR object if certain conditions are met (see Data Binding). The source object can also be an existing dependency object referenced either by name or by a relative position in the object graph. In Silverlight, you can bind to the target value of any dependency property. The source property value for a data binding need not be a dependency property; it can be a property on a CLR object if certain conditions are met (see Data Binding). The source object can also be an existing dependency object referenced either by name or by a relative position in the object graph.
That kind of documentation makes me want to fall down and cry. Who writes that crap? And the doc page does not include a single example to show what all those words mean. Listen, English is my first language. And I consider myself a .NET developer. But I cannot make any sense what-so-ever of that paragraph. The person or committee who wrote it should be taken out back and shot. Twice.
Even outside te MSDN pages, I haven't been able to find an example that actually shows how silverlight databbinding works. There are examples in MSDN that show things like
<Binding ...who cares? ....>
But I don't know what that "" thing is. It's not in my xaml and I don't think I want it in my xaml. What I have is an actual control, and a Rectangle within it. Can I specify the Grid.Column or Grid.Row of a rectangle via a databinding?
Now, I told you that the Rectangle lives within a Grid, which is a child of a UserControl.
<UserControl....
<Grid ...>
<Rectangle ...>
I get a code-behind file for the UserControl, it looks like this:
public partial class MyThing : UserControl
{
....
}
What if I want to bind te position of the rectangle within the grid (within the usercontrol) via an int property on the UserControl. Can I do that? Can I bind the Grid.RowProperty and Grid.ColumnProperty to something ? What if X and Y are like this:
public partial class MyThing : UserControl
{
public int X { get; set; }
public int Y { get; set; }
....
}
Can I bind that to the rectangle's grid.row and grid.column? How?
Please, someone clarify and give a simple example.
Upvotes: 1
Views: 1286
Reputation: 22492
Each FrameworkElement
has a DataContext
, which (if not null) is an instance of an arbitrary data class. You're binding to a property of that DataContext
.
<Rectangle Width="{Binding MyRectWidth}" x:Name="_myRect" />
Codebehind:
public class Foo
{
public double MyRectWidth { get; set; }
}
Foo foo = new Foo();
foo.MyRectWidth = 100;
_myRect.DataContext = foo;
The notation {Binding MyRectWidth}
is shorthand for {Binding Path=MyRectWidth}
.
You can specify other parameters for the binding, such as an instance of an object that implements IValueConverter
, to convert between the source and destination values.
The programmatic version of the XAML syntax is the Binding
object:
Binding b = new Binding();
b.Path = "MyRectWidth";
_myRect.SetBinding(Rectangle.WidthProperty, b);
A FrameworkElement
's DataContext
is in most cases inherited from its parent. You can see how this makes editing a more complex object fairly straightforward.
<UserControl x:Class="PersonEditControl">
<StackPanel>
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<TextBox Text="{Binding Address, Mode=TwoWay}" />
<TextBox Text="{Binding Phone, Mode=TwoWay}" />
</StackPanel>
</UserControl>
(You'll notice in this case I've set another property on the Binding: Mode=TwoWay
. This is necessary to propagate changes in the control back to the DataContext.)
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public partial class PersonEditControl
{
void SetPerson(Person p)
{
// child controls inherit this DataContext, if they are
// not explicitly given another:
DataContext = p;
}
}
At any point in the control hierarchy, you can specify a new DataContext
, and it will be inherited by children from that point downward.
Silverlight 3 introduces a new binding markup extension, ElementName
, which allows you to specify another XAML element as the Binding source. I played around with giving a name to my UserControl
(let's say _myControl
) and then specifying {Binding Path=PropertyName, ElementName=_myControl}
in a child control's property, but it didn't work.
I didn't spend much time on it and I might have missed something. At the very least, you can specify this relationship manually:
public partial class MyThing : UserControl
{
public int X { get; set; }
public int Y { get; set; }
public MyThing()
{
InitializeComponent(); // important to call this first: loads the XAML
_myRect.DataContext = this;
}
}
Another important piece in this puzzle is the interface INotifyPropertyChanged
. If your DataContext
implements this interface, and fires the PropertyChanged
event when its properties change, Bindings to those properties will pick up on the changes and propagate them to the control.
Upvotes: 4