2010-07-16 3 views
2

J'utilise l'architecture Model-View-ViewModel dans une application WPF que je suis en train de construire, et je voudrais qu'un ViewModel spécifique soit réellement réactif à la taille de la vue (pas une utilisation normale) -case de l'approche MVVM, je sais). Essentiellement, j'ai un objet ScrollViewer et je veux que le modèle de vue observe la largeur et la hauteur du scrollviewer et soit capable de faire les choses en conséquence en fonction de ce que sont la largeur et la hauteur.Liaison à ViewportWidth et ViewportHeight d'un ScrollViewer

Je voudrais faire quelque chose comme ceci:

<ScrollViewer ViewportWidth="{Binding Path=MyViewportWidth, Mode=OneWayToSource}" ViewportHeight="{Binding Path=MyViewportHeight, Mode=OneWayToSource}" /> 

Mais bien sûr, cela est impossible de le faire parce que « ViewportWidth » et « ViewportHeight » ne peut pas être « lié à » (agir alias comme des objectifs contraignants) parce qu'ils sont des propriétés de dépendance en lecture seule (même si je ne leur écris pas du tout dans cette liaison puisqu'il s'agit de OneWayToSource).

Quelqu'un sait-il une bonne méthode pour être en mesure de faire quelque chose comme ça?

Répondre

1

Vous pouvez essayer quelque chose en cours d'exécution ou onLoaded OnResizeChanged qui met à jour le viewmodel

private void ScrollViewer_Loaded(object sender, RoutedEventArgs e) 
{ 
    ScrollViewer sv = sender as ScrollViewer; 
    ViewModel vm = sv.DataContext as ViewModel; 

    vm.ScrollViewerHeight = sv.ViewportHeight; 
    vm.ScrollViewerWidth = sv.ViewportWidth; 
} 
1

Ok, c'est un vraiment vieille question, mais je pensais que je partage pour la postérité, depuis que je suis résolu ce problème un moi-même. La meilleure solution que j'ai trouvée est de créer un contrôle utilisateur qui dérive de la classe ScrollView et implémente les propriétés que vous voulez - qui sont bien sûr liées aux propriétés non-bindable de la classe de base.

Vous pouvez utiliser la fonction OnPropertyChanged pour surveiller ces propriétés et conserver les valeurs en synchronisation.

Voici le code complet de mon contrôle personnalisé appelé DynamicScrollViewer. Notez que j'ai quatre propriétés de dépendance liable appelées DynamicHorizontalOffset, DynamicVerticalOffset, DynamicViewportWidth et DynamicViewportHeight.

Les deux propriétés de décalage autorisent à la fois le contrôle en lecture et en écriture du décalage, tandis que les propriétés de la fenêtre d'affichage sont essentiellement en lecture seule.

Je devais utiliser cette classe lors de la création d'un contrôle d'éditeur d'animation complexe dans lequel différents composants (étiquettes à gauche, nœuds au milieu, timeline en haut) devaient défiler de manière synchrone, mais seulement de manière limitée. lié aux barres de défilement externes communes. Pensez à verrouiller une section de lignes dans une feuille de calcul, et vous obtenez l'idée.

using System.Windows; 
using System.Windows.Controls; 

namespace CustomControls 
{ 
    public partial class DynamicScrollViewer : ScrollViewer 
    { 
     public DynamicScrollViewer() 
     { 
      InitializeComponent(); 
     } 

     public double DynamicHorizontalOffset 
     { 
      get { return (double)GetValue(DynamicHorizontalOffsetProperty); } 
      set { SetValue(DynamicHorizontalOffsetProperty, value); } 
     } 

     public static readonly DependencyProperty DynamicHorizontalOffsetProperty = 
      DependencyProperty.Register("DynamicHorizontalOffset", typeof(double), typeof(DynamicScrollViewer)); 

     public double DynamicVerticalOffset 
     { 
      get { return (double)GetValue(DynamicVerticalOffsetProperty); } 
      set { SetValue(DynamicVerticalOffsetProperty, value); } 
     } 

     public static readonly DependencyProperty DynamicVerticalOffsetProperty = 
      DependencyProperty.Register("DynamicVerticalOffset", typeof(double), typeof(DynamicScrollViewer)); 

     public double DynamicViewportWidth 
     { 
      get { return (double)GetValue(DynamicViewportWidthProperty); } 
      set { SetValue(DynamicViewportWidthProperty, value); } 
     } 

     public static readonly DependencyProperty DynamicViewportWidthProperty = 
      DependencyProperty.Register("DynamicViewportWidth", typeof(double), typeof(DynamicScrollViewer)); 

     public double DynamicViewportHeight 
     { 
      get { return (double)GetValue(DynamicViewportHeightProperty); } 
      set { SetValue(DynamicViewportHeightProperty, value); } 
     } 

     public static readonly DependencyProperty DynamicViewportHeightProperty = 
      DependencyProperty.Register("DynamicViewportHeight", typeof(double), typeof(DynamicScrollViewer)); 

     protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
     { 
      base.OnPropertyChanged(e); 
      if (e.Property == DynamicVerticalOffsetProperty) 
      { 
       if (ScrollInfo != null) 
        ScrollInfo.SetVerticalOffset(DynamicVerticalOffset); 
      } 
      else if (e.Property == DynamicHorizontalOffsetProperty) 
      { 
       if (ScrollInfo != null) 
        ScrollInfo.SetHorizontalOffset(DynamicHorizontalOffset); 
      } 
      else if (e.Property == HorizontalOffsetProperty) 
      { 
       DynamicHorizontalOffset = (double)e.NewValue; 
      } 
      else if (e.Property == VerticalOffsetProperty) 
      { 
       DynamicVerticalOffset = (double)e.NewValue; 
      } 
      else if (e.Property == ViewportWidthProperty) 
      { 
       DynamicViewportWidth = (double)e.NewValue; 
      } 
      else if (e.Property == ViewportHeightProperty) 
      { 
       DynamicViewportHeight = (double)e.NewValue; 
      } 
     } 
    } 
} 
Questions connexes