2009-03-20 2 views
2

Ich habe ein kleines Datenbindungsproblem. (I haben in der Regel ...)WPF: Databinding - usercontrol verhält sich nicht

Dies ist der Fehler, den ich im Ausgabefenster zur Laufzeit erhalten:

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‘ ist eine Instanz von ‚UIKlokke‘, ein Usercontrol eine analoge Uhr darstellen.

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

und der Code hinter:

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)); 
    } 
} 

Wo ich dieses Usercontrol verwenden, möchte ich die Benutzersteuerelemente ‚klokke'-Eigenschaft auf die 'CurrentKlokke' Eigenschaft eines 'Game' Objekt binden.

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

CurrentKlokke ist eine Abhängigkeitseigenschaft.

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)); 
    } 

stelle ich die Datacontext für das Gitter der UIKlokke Instanz in Code enthält:

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

ich die ItemSource eines listbox auf eine andere Eigenschaft des Spiels Objektbindung, und es funktioniert gut.

Kann mir jemand mit diesem helfen?

Antwort

2

Versuchen Sie, die Klokke Eigenschaft aus der UIKlokke Entfernungssteuerung und binden die Datacontext des anaKlokke Objekt zum Klokke direkt.

Außerdem müssen Sie die Steuerung nicht innerhalb des Rasters innerhalb der Benutzersteuerung haben. Sie können nur die UserControls.Template verwenden:

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

diese Weise wird die Datacontext rechts direkt

auf dem Usercontrol Throught gesetzt Wenn Sie die Klokke im zugreifen müssen, um Code-behind können Sie verwenden

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

// use klokke 
+0

Das scheint zu funktionieren! Aber ich finde es ein bisschen seltsam. Aus meiner Sicht benötigt die Benutzersteuerung diese Eigenschaft, um "unabhängig" oder "vollständig" zu sein. Vielleicht ist etwas anders bei der Entwicklung von "echten" Kontrollen? – Vegar

+0

Der DataContext justs durchläuft den visuellen Baum und übernimmt nur die Rolle des übergeordneten Elements. – bendewey

+0

aktualisiert meine Antwort, ich bin mir nicht sicher, was genau Sie fragen. – bendewey

0

Ich bin mir nicht sicher, ich beginne gerade mit WPF. Aber sollten Sie Path nicht wie diese in Ihrer Bindung:

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

{Binding Path = Quelle} und {Binding source} ist das gleiche, soweit ich weiß. (Aber dann bin ich auch ein Anfänger ...) – Vegar

+0

@Vegar korrigieren sie sind die gleichen. – bendewey