Question

J'en ai deux séparés ItemsControls qui apparaissent côte à côte.Le ItemsControls se lier au même ItemsSource, mais ils affichent les données différemment.

Chaque élément affiché à gauche sera probablement plus petit que le même élément à droite.Cela pose un problème car les lignes ne s'alignent pas, j'ai donc besoin que l'élément de gauche soit lié à l'élément de droite.

ItemsControl        ItemsControl
|Item 1         |Item 1
|Item 2         |Item 2
|Item 3         |
|Item 4         |Item 3

Comme vous pouvez le voir, l'élément 2 à droite est plus grand, ce qui perturbe l'alignement.Donc, si je peux lier l'élément 2 de gauche à l'élément 2 de droite ActualHeight le problème serait résolu.Comment puis-je faire cela en XAML ?

Modifier: Pour rendre les choses plus compliquées, le ItemsControl à droite doit faire défiler de droite à gauche, mais les deux ItemsControls besoin de faire défiler vers le haut et vers le bas ensemble.Fondamentalement, celui de gauche fournit une sorte d’en-tête pour les éléments de droite.

Était-ce utile?

La solution

Suivi de Jobi Joy's répondre

Vous ne pouvez pas faire de direct OneWayToSource Liaison dans Xaml pour la propriété de dépendance ReadOnly ActualHeight, mais il existe de nombreuses solutions de contournement.La réponse par Kent Boogaart dans cette question est mon préféré.Ce qu'il fait, c'est qu'il utilise un comportement attaché qui écoute le SizeChanged événement de tout FrameworkElement et met à jour deux propriétés attachées, Largeur et Hauteur, en conséquence.

Avec un TextBlock Par exemple, ActualHeight peut être utilisé pour insérer une propriété Height du ViewModel comme

<TextBlock local:ActualSizeBehavior.ObserveActualSize="True"
           local:ActualSizeBehavior.ActualHeight="{Binding Path=Height,
                                                           Mode=OneWayToSource}"
           .../>

Synchronisez deux ScrollViewers
Vous pouvez soit utiliser un DependencyPropertyDescriptor être à l'écoute des changements dans VerticalOffsetProperty propriété ou souscrire au ScrollChanged événement et appel ScrollToVerticalOffset.Exemple

XML

<ScrollViewer Name="scrollViewerLeft"
              ScrollChanged="scrollViewerLeft_ScrollChanged">
<ScrollViewer Name="scrollViewerRight"
              ScrollChanged="scrollViewerRight_ScrollChanged">

Code derrière les gestionnaires d'événements

private void scrollViewerLeft_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    scrollViewerRight.ScrollToVerticalOffset(scrollViewerLeft.VerticalOffset);
}
private void scrollViewerRight_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    scrollViewerLeft.ScrollToVerticalOffset(scrollViewerRight.VerticalOffset);
}

ComportementTailleActuelle

public static class ActualSizeBehavior
{
    public static readonly DependencyProperty ActualSizeProperty =
        DependencyProperty.RegisterAttached("ActualSize",
                                            typeof(bool),
                                            typeof(ActualSizeBehavior),
                                            new UIPropertyMetadata(false, OnActualSizeChanged));
    public static bool GetActualSize(DependencyObject obj)
    {
        return (bool)obj.GetValue(ActualSizeProperty);
    }
    public static void SetActualSize(DependencyObject obj, bool value)
    {
        obj.SetValue(ActualSizeProperty, value);
    }
    private static void OnActualSizeChanged(DependencyObject dpo,
                                            DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = dpo as FrameworkElement;
        if ((bool)e.NewValue == true)
        {
            element.SizeChanged += element_SizeChanged;
        }
        else
        {
            element.SizeChanged -= element_SizeChanged;
        }
    }

    static void element_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        SetActualWidth(element, element.ActualWidth);
        SetActualHeight(element, element.ActualHeight);
    }

    private static readonly DependencyProperty ActualWidthProperty =
        DependencyProperty.RegisterAttached("ActualWidth", typeof(double), typeof(ActualSizeBehavior));
    public static void SetActualWidth(DependencyObject element, double value)
    {
        element.SetValue(ActualWidthProperty, value);
    }
    public static double GetActualWidth(DependencyObject element)
    {
        return (double)element.GetValue(ActualWidthProperty);
    }

    private static readonly DependencyProperty ActualHeightProperty =
        DependencyProperty.RegisterAttached("ActualHeight", typeof(double), typeof(ActualSizeBehavior));
    public static void SetActualHeight(DependencyObject element, double value)
    {
        element.SetValue(ActualHeightProperty, value);
    }
    public static double GetActualHeight(DependencyObject element)
    {
        return (double)element.GetValue(ActualHeightProperty);
    }
}

Autres conseils

Depuis le ItemsSource est le même sur les deux, vous pouvez en utiliser un seul ItemsControl et une ligne entière représentée comme deux sections (deux colonnes d'une grille) à l'intérieur de cette seule DataTemplate, les hauteurs seront alors alignées automatiquement.Vous pouvez toujours lui donner l'impression qu'il fait partie de deux ItemsControl mais techniquement un.

Une autre façon de procéder consiste à ajouter une propriété Height au ViewModel (bien sûr, la conception n'est pas très correcte depuis l'ajout de la dépendance View à la VM).TwoWay lie la hauteur à la ActualHeight du left-itemsControl ItemContainerStyle.Et sur le contrôle d'éléments de droite, liez cette propriété Height à la hauteur de ItemsContainerStyle {One Way}.Les deux seront donc synchronisés.

Une autre idée basée sur votre mise à jour 'Besoin du scroll sur le côté droit' :Utilisez un seul ListView et contient deux colonnes, et parmi ces deux GridViewColumn.CellTemplate avez vos deux DataTemplates.Cette idée nécessite encore un gel de colonne sur la première colonne.Mais cela risque d'être plus délicat.

Quoi qu'il en soit, j'opterais pour la première approche ici.

Jetez un oeil à mon article: http://www.codeproject.com/KB/WPF/BindingHub.aspx

Voici comment vous pouvez vous lier aux propriétés de dépendance en lecture seule à l'aide de BindingHub :

<bindings:BindingHub 
       Visibility="Hidden"
       Socket1="{Binding ActualWidth, ElementName=Item, Mode=OneWay}"
       Socket2="{Binding ItemWidth, Mode=OneWayToSource}"
       Connect="(1 in, 2 out)"/>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top