2009-03-20 9 views
2

J'ai un petit problème de liaison de données. (J'ai l'habitude ...)WPF: Liaison de données - usercontrol ne se comporte pas

Ceci est l'erreur que je reçois dans la fenêtre de sortie lors de l'exécution:

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 » est une instance de « UIKlokke », un usercontrol représentant une horloge analogique.

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

et le code derrière:

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

Là où j'utilise cette usercontrol, je veux lier les klokke' de-propriété à la 'usercontrols' propriété d'un 'CurrentKlokke objet Jeu'.

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

CurrentKlokke est une propriété de dépendance.

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

Je mis le DataContext pour la grille contenant l'instance UIKlokke dans le code:

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

Je liant le ItemSource d'une zone de liste à une autre propriété de l'objet du jeu, et il fonctionne très bien.

Quelqu'un peut-il m'aider avec celui-ci?

Répondre

2

Essayez de supprimer la propriété Klokke du contrôle UIKlokke et lient le DataContext de l'objet anaKlokke au Klokke directement.

De même, vous n'avez pas besoin d'avoir le contrôle dans la grille à l'intérieur de la commande usercontrol. Vous pouvez simplement utiliser le UserControls.Template:

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

De cette façon, le DataContext est situé throught directement au UserControl

Si vous devez accéder au Klokke dans le code-behind vous pouvez utiliser

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

// use klokke 
+0

Cela semble fonctionner! Mais je trouve cela un peu étrange, cependant. De mon point de vue, l'usercontrol a besoin de cette propriété pour être "autonome", ou "complète". Peut-être que les choses sont différentes lors du développement de contrôles «réels»? – Vegar

+0

Le jus de données DataContext continue à traverser l'arbre visuel, et prend juste le rôle du parent. – bendewey

+0

mis à jour ma réponse, je ne suis pas sûr exactement ce que vous demandez. – bendewey

0

Je ne sais pas à ce sujet, je ne fais que commencer avec WPF. Mais vous ne devriez pas utiliser Path dans votre fixation comme ceci:

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

{Binding Path = source} et {Binding source} est la même chose pour autant que je sache. (Mais alors, je suis un débutant aussi ...) – Vegar

+0

@Vegar correct ils sont les mêmes. – bendewey

Questions connexes