Why does databinding not work?
I have a car-class like this:
public class car
{
public String Name {get; private set;}
public car(string name)
{
this.Name = name;
}
}
I also have a userControl:
public partial class CarListItem : UserControl
{
private Car car;
public CarListItem (Car car)
{
InitializeComponent();
this.car= car;
}
}
With xaml:
<Grid>
<Label Content="{Binding Path=car.Name}" Name="lblCarName"/>
</Grid>
but the dat开发者_如何学编程abinding does not work. What am I doing wrong?
I want to show the name of the car on the userControl.
You should not need to preface the binding expression with car...
<Grid>
<Label Content="{Binding Name}" Name="lblCarName"/>
</Grid>
...in addition you need to set the DataContext
of your UserControl
public partial class CarListItem : UserControl
{
public CarListItem (Car car)
{
InitializeComponent();
this.DataContext = car;
}
}
Also my assumption is that you are passing a name in to the ctor of car other then an empty string or null.
For a binding to work, you need to have a value in a Control
's DataContext property. It can also be inherited. So, child controls can also access parent's DataContext
if they don't have one.
Properties (not even public) do not help with binding unless used with Self Binding
.
To make your code work,
Replace
this.car = car;
With
this.DataContext = car;
And Replace
<Label Content="{Binding Path=car.Name}" Name="lblCarName"/>
With
<Label Content="{Binding Path=Name}" Name="lblCarName"/>
Your binding binds to the datacontext's car.Name
. In your case, the DataContext is NULL.
You have several options:
- Set the data context to the
CarListItem
instance - Specify binding source.
The first option is usually better.
Even better idea would be to define a DataTemplate
for your Car
, and use a list of Car
s instead of explicit CarListItem
s:
<DataTemplate DataType="{x:Type local:Car}">
<Grid>
<Label Content="{Binding Path=Name}"/>
</Grid>
</DataTemplate>
Now, you can use this template as ItemTemplate
in the list.
Using this.DataContext
will work, but it's fragile and horrible and not a good way to design your application. If I were to consume your user control and write this xaml:
<CarListItem DataContext="{Binding MyThing}" />
... then your control will break, regardless of whether the Car
property is correctly set or not. That's not very pretty.
A more robust approach is to mark your UserControl
element in Xaml with an x:Name
, and use ElementName
in your binding. So, your control looks something like this:
<UserControl x:Name="control" ....... (namespaces/etc here)>
<Grid>
<Label Content="{Binding Car.Name, ElementName=control}" Name="lblCarName"/>
</Grid>
Now, if you want to set DataContext
on the Grid
(using DataContext="{Binding Car, ElementName=control}"
), you can get the benefit of datacontext in a more robust way.
However, for any of this to work, you need to be exposing your car
field as a property, rather than just as a field. You also need to implement INotifyPropertyChanged
so that the UI realises when you change the value of the property, though you can work around this temporarily by setting car
before you call InitializeComponent()
in your constructor.
精彩评论