2009-07-26 6 views
1

Comment lier un élément d'un <UserControl> dérivé à un élément de la base <UserControl>?XAML - Comment lier un élément d'un <UserControl> dérivé à un élément de la base <UserControl>?

J'ai défini un UserControl appelé Tile comme ma classe de base. Ce serait une classe de base abstraite, si XAML ne rechignait pas quand j'essayais d'instancier un objet dérivé de celui-ci ...

De toute façon, jusqu'à présent, Tile ne contient qu'une seule propriété de dépendance: OuterShape. C'est un objet System.Windows.Shapes.Shape (aussi abstrait). Ainsi: toutes les tuiles auront une sorte de forme visuelle associée à elles, pour le rendu. Mais il y a beaucoup de différents types de tuiles --- certains avec System.Windows.Shapes.Paths, certains avec System.Windows.Shapes.Polygons, etc.

Donc maintenant je travaille sur le premier UserControl dérivé: PolyTile. Comme son nom l'indique, il s'agit d'un Tile qui utilise un System.Windows.Shapes.Polygon comme propriété "OuterShape".

Le problème que je rencontre est que je n'arrive pas à comprendre comment lier correctement l'élément XAML <Polygon> à la propriété Shape dans la classe de base.

/************ 
** Tile.cs ** 
************/ 
// This class contains a generic shape, and that's all. 
// This class does NOT have a XAML file to go with it. It is purely code implemented. 
public class Tile : System.Windows.Controls.UserControl 
{ 
    public static readonly System.Windows.DependencyProperty OuterShapeProperty 
     = System.Windows.DependencyProperty.Register( "OuterShape", 
                 typeof(System.Windows.Shapes.Shape), 
                 typeof(Tile)); 
    public System.Windows.Shapes.Shape OuterShape 
    { get { return (System.Windows.Shapes.Shape)GetValue(OuterShapeProperty); } 
     set { SetValue(OuterShapeProperty, (System.Windows.Shapes.Shape)value); } 
    } 
} 

........................

<!--***************** 
*** PolyTile.xaml *** 
******************--> 
<local:Tile x:Name="__PolyTile__" x:Class="WPFApplication1.PolyTile" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WPFApplication1"> 
    <Grid Name="grdMain"> 
     <Polygon Name="OuterPoly" /> 
      <!--OuterPoly needs to be data-bound (OneWay) 
      to the OuterShape property of the Tile UserControl. 
      That way, when my derived class sets OuterShape to a new <Polygon> element, 
      OuterShape will show up on the screen as a <Polygon>--> 
    </Grid> 
</local:Tile> 

......... ...............

/**************** 
** PolyTile.cs ** 
****************/ 
// This class encapsulates a tile that is in the shape of a specified <Polygon> element. 
/// <summary> 
/// Interaction logic for PolyTile.xaml 
/// </summary> 
public partial class PolyTile : Tile // Derived from Tile 
{ 
    public PolyTile() 
    { 
     InitializeComponent(); 

     System.Windows.Data.BindingExpressionBase BindExp; 
     PolyConverter polyConverter = new PolyConverter(); 

     System.Windows.Data.Binding PolyBinding = new System.Windows.Data.Binding("OuterPoly"); 
     PolyBinding.Source = __PolyTile__; 
     PolyBinding.Mode = System.Windows.Data.BindingMode.OneWayToSource; 
     PolyBinding.Converter = polyConverter; 
     BindExp = __PolyTile__.SetBinding(Tile.OuterShapeProperty, PolyBinding); 
    } 



    // The framework won't convert a base object into a derived object without an explicit cast ... 
    // ... in this case, that means I have to make a custom DataConverter. 
    [System.Windows.Data.ValueConversion(typeof(System.Windows.Shapes.Polygon), typeof(System.Windows.Shapes.Shape))] 
    protected class PolyConverter : System.Windows.Data.IValueConverter 
    { 
     public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { return value; } 
     // OneWayToSource binding: Thus the Convert method is never used. 
     // Rather, ConverBack is used to cast the base <Shape> into a derived <Polygon> 

     public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value.GetType() == typeof(System.Windows.Shapes.Polygon)) 
       return value; 
      else 
       return System.Windows.DependencyProperty.UnsetValue; 
     } 
    } 
} 

je ne vois aucun moyen possible de régler cette liaison en XAML. (Bien que je ne comprenne pas assez bien DataContexts pour dire que j'ai pensé à tout ...)

Par conséquent, j'ai essayé de régler manuellement la liaison dans le code retour. J'ai essayé plusieurs façons d'organiser le chemin de liaison et les éléments source et cible. Chaque fois que je reçois une exception fatale ou un PathError ou un UpdateSourceError quelque chose de similaire.

Est-ce que quelqu'un sait ce que je fais mal?
Tout conseil est grandement apprécié!

Répondre

0

Il peut être fait en utilisant objet syntaxe XAML

Il est important de noter que le contexte de données par défaut fonctionne parfaitement, et des problèmes se poseront si vous essayez d'obtenir très explicite Par exemple:.. la liaison échouera si vous ajoutez ElementName="__PolyTile__" à la contraignant.

Il apparaît également que le convertisseur de données n'est pas requis dans cette solution. Cela rend le code beaucoup plus facile à suivre, mais peut-être au prix d'un peu de sécurité.

<!--***************** 
*** PolyTile.xaml *** 
******************--> 
<local:Tile x:Name="__PolyTile__" x:Class="WPFApplication1.PolyTile" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WPFApplication1"> 

    <local:Tile.OuterShape> 
     <Binding Path="OuterPoly" Mode="OneWayToSource" /> 
    </local:Tile.OuterShape> 

    <Grid Name="grdMain"> 
     <Polygon Name="OuterPoly" /> 
    </Grid> 

</local:Tile> 
2

vous pouvez le faire de deux façons

vous pouvez utiliser la source relative: -

<TextBlock 
    Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ParentUserControl}}, Path=MyProperty}" /> 

ou vous pouvez utiliser des liaisons de nom de l'élément, qui je pense sont plus faciles à lire. (Vous devez utiliser x. Syntaxe de nom sur le contrôle de l'utilisateur de nommer le contrôle entier dans le fichier XAML

<TextBlock 
    Text="{Binding ElementName=childUserControl, Path=MyProperty}" /> 

here est un petit projet de test je l'ai écrit pour tester cette

+0

Cela répond presque à ma question. Pourriez-vous réécrire un peu ce code, afin que vous liez le contrôle TextBox enfant à une propriété TextBox du parent? J'essaie de lier le contrôle lui-même - pas seulement une propriété du contrôle, comme "Texte" – Giffyguy

Questions connexes