views:

1482

answers:

2

I have a little databinding-problem. (I usually have...)

This is the error I get in the output window at runtime:

System.Windows.Data Error: 39 : BindingExpression path error: 'CurrentKlokke' property not found on 'object' ''UIKlokke' (Name='anaKlokke')'. BindingExpression:Path=CurrentKlokke; DataItem='UIKlokke' (Name='anaKlokke'); target element is 'UIKlokke' (Name='anaKlokke'); target property is 'klokke' (type 'Klokke')

'anaKlokke' is a instance of 'UIKlokke', a usercontrol representing an analog clock.

    <UserControl
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Klokketrening"
        mc:Ignorable="d"
        x:Class="Klokketrening.UIKlokke"
        x:Name="UserControl"
        DataContext="{Binding RelativeSource={RelativeSource self}}"
        d:DesignWidth="400" d:DesignHeight="400">

        <UserControl.Resources>
            <ControlTemplate x:Key="clockTemplate">
                <Grid>
                    <Grid.Resources>
                        <local:TimeTilVinkel x:Key="hourToAngle"/>
                        <local:MinuttTilVinkel x:Key="minuteToAngle"/>
                    </Grid.Resources>
                    <Grid.LayoutTransform>
                        <ScaleTransform ScaleX="2" ScaleY="2" />
                    </Grid.LayoutTransform>
                    <Ellipse Width="108" Height="108" StrokeThickness="3">
                        <Ellipse.Stroke>
                            <LinearGradientBrush>
                                <GradientStop Color="LightBlue" Offset="0" />
                                <GradientStop Color="DarkBlue" Offset="1" />
                            </LinearGradientBrush>
                        </Ellipse.Stroke>
                    </Ellipse>


                    <Canvas Width="102" Height="102">
                        <Ellipse Width="8" Height="8" Fill="Black" Canvas.Top="46" Canvas.Left="46" />
                        <Rectangle x:Name="HourHand" Canvas.Top="26" Canvas.Left="48" Fill="Black" Width="4" Height="25">
                            <Rectangle.RenderTransform>
                                <RotateTransform x:Name="HourHand2" CenterX="2" CenterY="25" Angle="{Binding Converter={StaticResource hourToAngle}}" />                     
                            </Rectangle.RenderTransform>
                        </Rectangle>
                        <Rectangle x:Name="MinuteHand" Canvas.Top="16" Canvas.Left="49" Fill="Black" Width="2" Height="35">
                            <Rectangle.RenderTransform>
                                <RotateTransform CenterX="1" CenterY="35" Angle="{Binding Converter={StaticResource minuteToAngle}}" />
                            </Rectangle.RenderTransform>
                        </Rectangle>
                    </Canvas>
                </Grid>
            </ControlTemplate>
        </UserControl.Resources>
        <Grid>
            <Control Template="{StaticResource clockTemplate}" DataContext="{Binding klokke}" />
        </Grid> 
    </UserControl>

and the code behind:

public partial class UIKlokke
{

    public Klokke klokke
    {
        get {return (Klokke)GetValue(UIKlokke.KlokkeProperty); }
        set { SetValue(UIKlokke.KlokkeProperty, value); } 
    }

    public static readonly DependencyProperty KlokkeProperty;

 public UIKlokke()
 {
  this.InitializeComponent();
 }

    static UIKlokke()
    {
        UIKlokke.KlokkeProperty = DependencyProperty.Register("klokke", typeof(Klokke), typeof(UIKlokke));
    }
}

Where I use this usercontrol, I want to bind the usercontrols 'klokke'-property to the 'CurrentKlokke' property of an 'Game' object.

<local:UIKlokke x:Name="anaKlokke" Grid.Column="0" Grid.Row="1" klokke="{Binding CurrentKlokke}"/>

CurrentKlokke is a dependencyproperty.

    public Klokke CurrentKlokke
    {
        get { return (Klokke)GetValue(Game.CurrentKlokkeProperty); }
        set { SetValue(Game.CurrentKlokkeProperty, value);  }
    }
    public static readonly DependencyProperty CurrentKlokkeProperty;

    static Game()
    {
        Game.CurrentKlokkeProperty = DependencyProperty.Register("CurrentKlokke", typeof(Klokke), typeof(Game));
    }

I set the DataContext for the grid containing the UIKlokke instance in code:

        _game = new Game(Game.GameLevel.Easy, 10);
        gridGameUI.DataContext = _game;

I'm binding the itemsource of a listbox to another property of the Game object, and it works fine.

Can anybody help me out with this one?

A: 

Not sure about this, I'm just starting with WPF. But shouldn't you use Path in your binding like this:

<local:UIKlokke x:Name="anaKlokke"  
                Grid.Column="0" Grid.Row="1" 
                klokke="{Binding Path=CurrentKlokke}"/>
Anthony Brien
{Binding Path=source} and {Binding source} is the same thing as far as I know. (But then, I'm a beginner too...)
Vegar
@Vegar correct they are the same.
bendewey
+2  A: 

Try removing the Klokke property from the UIKlokke control and bind the anaKlokke object's DataContext to the Klokke directly.

Also, you don't need to have the Control inside the grid inside the usercontrol. You can just use the UserControls.Template:

<UserControl ... DataContext="No needed its set on the game">
  <UserControl.Template>
    <ControlTemplate>
      <Grid>
        <!-- ... -->
      </Grid>
    </ControlTemplate>
  </UserControl.Template>
</UserControl>

This way the DataContext is set right throught directly to the UserControl

If you need to access the Klokke in the code-behind you can use

var klokke = DataContext as Klokke;
if (klokke == null) return;

// use klokke
bendewey
This seems to work! But I find it a little bit strange, though. From my point of view, the usercontrol needs this property to be 'self contained', or 'complete'. Maybe thing are different when developing 'real' controls?
Vegar
The DataContext justs keeps passing through the visual tree, and just takes on the roll of the parent.
bendewey
updated my answer, I'm not sure exactly what your asking.
bendewey
It is self-contained its just contained inside a base classes property of DataContext.
bendewey
I'm not completely sure what I'm asking my self. WPF continuously puzzles me. You can do everything, and it's so simple, but than again, it's so complicated to understand... :-/ But your answer works for me.
Vegar
I feel your pain very much. Have you gotten your head around commands and attached properties yet. Boy oh boy, eye opening, powerful, yet confusing as hell.
bendewey
I have read through WPF Unleashed, and my head's spinning alright.. It's very exiting, but I'm a delphi programmer of profession so I don't get to practice much
Vegar