开发者

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:

  1. Set the data context to the CarListItem instance
  2. 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 Cars instead of explicit CarListItems:

<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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜