2009-07-26 8 views
2

J'ai besoin de quelque chose pour obtenir la position d'un sous-sous-élément par rapport au conteneur. TransformToAncestor fait cela. Cependant, l'élément et les sous-éléments se déplacent, redimensionnent le changement, leur disposition, etc. J'ai besoin d'un moyen de garder la position à jour. Comme un événement si quelque chose se passe qui affecterait mon opération TransformToAncestor. Ou une propriété de dépendance "AbsolutePosition" à laquelle je peux me lier.Lier à la position de l'élément par rapport à un parent dans WPF

Contexte:

que je fais en quelque sorte un éditeur de flux de travail. Il existe des 'modules' qui ont un ou plusieurs ports et lignes qui relient les modules d'un port à un autre.

La stucture XAML ressemble à ceci:

<Canvas> 
    <Module Left="..." Top="..." Width="..." Height="..."> 
    <Grid><otherelement><somemorelayouting> 
     <Port Name="a" /> 
     <Port Name="b" /> 
    </somemorelayouting></otherelement></Grid> 
    </Module> 
    <Module Left="..." Top="..." Width="..." Height="..."> 
    <differentsetoflayouts> 
    <Port Name="c" /> 
    <Port Name="d" /> 
    </differentsetoflayouts> 
    </Module> 
    <Line startpoint="{binding source=a, path=abs_position}" endpoint="{binding source=c, path=abs_position}" /> 
</Canvas> 

La ligne relie le port a du premier module avec le port B de la seconde. Les points d'extrémité doivent être dans le coin supérieur gauche de l'élément port (pour le moment). Cette propriété "abs_position" utilisée dans cet exemple n'existe pas forcément (j'utilise start/endpoint ici au lieu de X1, X2, Y1, Y2 uniquement pour améliorer la lisibilité)

Répondre

2

Si vous implémentez votre conteneur avec les propriétés de dépendance attachées pour l'emplacement des éléments enfants (comme le panneau Canvas fait, ce qui semble être le cas selon le code fourni), alors vous pouvez lier aux changements de cette propriété de dépendance en utilisant un DependencyPropertyDescriptor.

DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(Canvas.TopProperty, typeof(Canvas)); 

dpd.AddValueChanged(canvas1, new EventHandler(topChangedCallback)); 
+0

le problème est que le module est un UserControl avec une structure interne assez complexe, en utilisant plusieurs conteneurs imbriqués de type différent. Pour aggraver les choses, une partie de cette structure est créée dynamiquement. Je devrais ajouter des écouteurs d'événement à chaque conteneur, chacun utilisant d'autres propriétés pour le positionnement. Cela fonctionnerait, mais ce n'est guère une bonne solution. J'espérais une solution qui ne laisse pas le code XAML et C# encombré avec l'enregistrement/désenregistrement d'événement. – Stefan

+0

Eh bien, alors, pourquoi avez-vous demandé à propos d'un DependencyProperty vous pouvez vous lier à? –

+0

Eh bien, je ne l'ai pas fait. J'ai demandé "un moyen de garder la position à jour". Je viens de mentionner la propriété de dépendance "AbsolutePosition" et les événements comme une approche possible. Désolé, j'espérais que la question soit plus claire de cette façon.Il semble que j'ai échoué. – Stefan

3

Je propose d'utiliser la solution de kek444 avec une disposition personnalisée si possible. Cependant, si cela ne s'applique pas, voici une autre approche que j'ai trouvée en parcourant les conseils de kek444.

L'événement UIElement.LayoutUpdated est déclenché chaque fois que quelque chose change sur la mise en page. Il réagit au mouvement, redimensionne, ajoute/enlève des éléments, et à propos de n'importe quoi d'autre. Il ne se déclenche pas seulement si l'élément est affecté sur lequel l'événement est enregistré, mais également si tout autre élément utilisant le même fil d'envoi est touché. En conséquence, il est tiré très souvent, donc l'utiliser pourrait avoir un impact sur les performances.

Voir aussi le billet de Dave Relyea. Stackoverflow ne me laisse pas publier deux liens, donc juste google pour "Layout Events - SizeChanged and LayoutUpdated".

Questions connexes