2010-11-05 1 views
0

Je suis plutôt nouveau chez WPF et j'ai besoin d'aide.WPF: Empêcher la mise à l'échelle de BorderThickness

J'ai une ViewBox sur mon et pour la ViewBox une ellipse et une bordure. Lorsque je redimensionne le formulaire, je souhaite que l'ellipse et la bordure soient automatiquement mises à l'échelle (ce qu'elles font). Mais je ne veux pas que le paramètre BorderThickness soit mis à l'échelle. L'épaisseur de la bordure devrait rester 3 pixels.

Est-ce que quelqu'un sait comment accomplir cela?

Voici mon XAML:

<Window 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
x:Class="StretchTest.MainWindow" 
x:Name="Window" 
Title="MainWindow" 
Width="700" Height="400"> 

<Grid x:Name="LayoutRoot"> 
    <Viewbox> 
     <Grid Height="300" Width="400" HorizontalAlignment="Center" VerticalAlignment="Center"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="0"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="0"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="1"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="1"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="2"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="2"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="3"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="3"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="0"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="0"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="1"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="1"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="2"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="2"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="3"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="3"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="0"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="0"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="1"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="1"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="2"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="2"/> 
      <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="3"/> 
      <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="3"/> 
     </Grid> 
    </Viewbox> 
</Grid> 

Merci pour toute aide!

Répondre

0

Je suggère de ne pas utiliser une ViewBox. Si vous ne définissez pas la largeur et la hauteur de l'ellipse et de la bordure, elles seront automatiquement dimensionnées avec la fenêtre. Au lieu d'utiliser une grille pour définir la taille relative des contrôles en utilisant des pourcentages hauteur de ligne et la largeur de colonne (. par exemple 0,6 *)


Mise à jour - Exemple

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="0.4*" /> 
     <ColumnDefinition Width="0.6*" /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 

    <Border Grid.Row="1" Name="border1" BorderBrush="Black" BorderThickness="1" Padding="2"> 
     <Ellipse Name="ellipse1" Stroke="Black" Grid.Row="1" Stretch="UniformToFill" /> 
    </Border> 
</Grid> 

Update

Hmmm, ne pas voir un moyen facile de faire exactement ce dont vous avez besoin. Voici le plus proche que j'ai pu venir. Les seules autres options que je peux voir:

  1. soumettons chaque ellipse dans sa propre boîte de vue
  2. Taille des colonnes de la grille & lignes dans le code dans la fenêtre redimensionner

    <Grid HorizontalAlignment="Center" VerticalAlignment="Center"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="*"/> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="0" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="0"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="1" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="1"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="2" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="2"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="3" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="3"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="0" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="0"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="1" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="1"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="2" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="2"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="3" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="3"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="0" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="0"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="1" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="1"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="2" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="2"/> 
        <Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="3" Stretch="UniformToFill"/> 
        <Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="3"/> 
    </Grid> 
    
+0

Merci pour votre suggestion Thomas. Le problème est que l'ellipse et la bordure doivent s'étendre = uniforme. Seul BorderThickness ne devrait pas. Si je place l'Ellipse et la Bordure dans une cellule, comment puis-je spécifier que la grille devrait s'étendre = uniforme? – Jackerd

+0

J'ai ajouté un exemple à ma réponse, j'espère que cela aide – Thomas

+0

Merci Thomas, j'ai vérifié votre exemple, mais ce n'est pas exactement ce dont j'ai besoin. J'ai réussi à ajouter mon XAML dans ma question. Le comportement est exactement ce dont j'ai besoin, mais seul le BorderThickness ne devrait pas s'étirer. – Jackerd

0

En tant solution alternative (si quelqu'un trouve cette question plus tard) pour empêcher la mise à l'échelle de BorderThickness, vous pouvez utiliser une version personnalisée de Viewbox avec un convertisseur spécial.

Viewbox habituelle, mais maintenant, avec une lecture seule Scale propriété et statique ThicknessConverter:

public class BorderyViewbox : Decorator { 
    public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(nameof(Stretch), 
      typeof(Stretch), typeof(BorderyViewbox), new FrameworkPropertyMetadata(Stretch.Uniform, FrameworkPropertyMetadataOptions.AffectsMeasure)); 

    public Stretch Stretch { 
     get { return (Stretch)GetValue(StretchProperty); } 
     set { SetValue(StretchProperty, value); } 
    } 

    public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register(nameof(StretchDirection), 
      typeof(StretchDirection), typeof(BorderyViewbox), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure)); 

    public StretchDirection StretchDirection { 
     get { return (StretchDirection)GetValue(StretchDirectionProperty); } 
     set { SetValue(StretchDirectionProperty, value); } 
    } 

    public static readonly DependencyPropertyKey ScalePropertyKey = DependencyProperty.RegisterReadOnly(nameof(Scale), typeof(Size), 
      typeof(BorderyViewbox), new PropertyMetadata(default(Size))); 

    public static readonly DependencyProperty ScaleProperty = ScalePropertyKey.DependencyProperty; 

    public Size Scale => (Size)GetValue(ScaleProperty); 

    private ContainerVisual InternalVisual { 
     get { 
      if (_internalVisual == null) { 
       _internalVisual = new ContainerVisual(); 
       AddVisualChild(_internalVisual); 
      } 
      return _internalVisual; 
     } 
    } 

    private UIElement InternalChild { 
     get { 
      var vc = InternalVisual.Children; 
      return vc.Count != 0 ? vc[0] as UIElement : null; 
     } 
     set { 
      var vc = InternalVisual.Children; 
      if (vc.Count != 0) vc.Clear(); 
      vc.Add(value); 
     } 
    } 

    private Transform InternalTransform { 
     get { return InternalVisual.Transform; } 
     set { InternalVisual.Transform = value; } 
    } 

    public override UIElement Child { 
     get { return InternalChild; } 
     set { 
      var old = InternalChild; 
      if (!ReferenceEquals(old, value)) { 
       RemoveLogicalChild(old); 

       if (value != null) { 
        AddLogicalChild(value); 
       } 

       InternalChild = value; 
       InvalidateMeasure(); 
      } 
     } 
    } 

    protected override int VisualChildrenCount => 1; 

    protected override Visual GetVisualChild(int index) { 
     if (index != 0) throw new ArgumentOutOfRangeException(nameof(index)); 
     return InternalVisual; 
    } 

    protected override IEnumerator LogicalChildren => InternalChild == null ? EmptyEnumerator.Instance : new SingleChildEnumerator(InternalChild); 

    protected override Size MeasureOverride(Size constraint) { 
     var child = InternalChild; 
     var parentSize = new Size(); 

     if (child != null) { 
      var infinteConstraint = new Size(double.PositiveInfinity, double.PositiveInfinity); 

      child.Measure(infinteConstraint); 
      var childSize = child.DesiredSize; 

      var scale = ComputeScaleFactor(constraint, childSize, Stretch, StretchDirection); 
      SetValue(ScalePropertyKey, scale); 

      parentSize.Width = scale.Width * childSize.Width; 
      parentSize.Height = scale.Height * childSize.Height; 
     } 

     return parentSize; 

    } 

    protected override Size ArrangeOverride(Size arrangeSize) { 
     var child = InternalChild; 
     if (child != null) { 
      var childSize = child.DesiredSize; 

      var scale = ComputeScaleFactor(arrangeSize, childSize, Stretch, StretchDirection); 
      SetValue(ScalePropertyKey, scale); 

      InternalTransform = new ScaleTransform(scale.Width, scale.Height); 
      child.Arrange(new Rect(new Point(), child.DesiredSize)); 

      arrangeSize.Width = scale.Width * childSize.Width; 
      arrangeSize.Height = scale.Height * childSize.Height; 
     } 
     return arrangeSize; 
    } 

    private static Size ComputeScaleFactor(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection) { 
     var scaleX = 1.0; 
     var scaleY = 1.0; 

     var isConstrainedWidth = !double.IsPositiveInfinity(availableSize.Width); 
     var isConstrainedHeight = !double.IsPositiveInfinity(availableSize.Height); 

     if ((stretch == Stretch.Uniform || stretch == Stretch.UniformToFill || stretch == Stretch.Fill) 
       && (isConstrainedWidth || isConstrainedHeight)) { 
      scaleX = Equals(0d, contentSize.Width) ? 0.0 : availableSize.Width/contentSize.Width; 
      scaleY = Equals(0d, contentSize.Height) ? 0.0 : availableSize.Height/contentSize.Height; 

      if (!isConstrainedWidth) { 
       scaleX = scaleY; 
      } else if (!isConstrainedHeight) { 
       scaleY = scaleX; 
      } else { 
       switch (stretch) { 
        case Stretch.Uniform: 
         var minscale = scaleX < scaleY ? scaleX : scaleY; 
         scaleX = scaleY = minscale; 
         break; 

        case Stretch.UniformToFill: 
         var maxscale = scaleX > scaleY ? scaleX : scaleY; 
         scaleX = scaleY = maxscale; 
         break; 

        case Stretch.Fill: 
         break; 
       } 
      } 

      switch (stretchDirection) { 
       case StretchDirection.UpOnly: 
        if (scaleX < 1.0) scaleX = 1.0; 
        if (scaleY < 1.0) scaleY = 1.0; 
        break; 

       case StretchDirection.DownOnly: 
        if (scaleX > 1.0) scaleX = 1.0; 
        if (scaleY > 1.0) scaleY = 1.0; 
        break; 

       case StretchDirection.Both: 
        break; 
      } 
     } 

     return new Size(scaleX, scaleY); 
    } 

    private ContainerVisual _internalVisual; 

    #region Converter-related stuff 
    private class ConverterInner : IValueConverter { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
      if (!(value is Size)) return parameter; 

      var scale = (Size)value; 
      var thickness = parameter as Thickness? ?? new Thickness(1d); 

      return new Thickness(thickness.Left/scale.Width, thickness.Top/scale.Height, 
        thickness.Right/scale.Width, thickness.Bottom/scale.Height); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 
      if (!(value is Size)) return parameter; 

      var scale = (Size)value; 
      var thickness = parameter as Thickness? ?? new Thickness(1d); 

      return new Thickness(thickness.Left * scale.Width, thickness.Top * scale.Height, 
        thickness.Right * scale.Width, thickness.Bottom * scale.Height); 
     } 
    } 

    public static IValueConverter ThicknessConverter { get; } = new ConverterInner(); 
    #endregion 

} 

Exemple d'utilisation:

<BorderyViewbox x:Name="Viewbox"> 
    <Border BorderBrush="Red" SnapsToDevicePixels="True"> 
     <Border.BorderThickness> 
      <Binding Path="Scale" ElementName="Viewbox" Converter="{x:Static BorderyViewbox.ThicknessConverter}"> 
       <Binding.ConverterParameter> 
        <Thickness>3</Thickness> 
       </Binding.ConverterParameter> 
      </Binding> 
     </Border.BorderThickness> 
    </Border> 
</BorderyViewbox> 

version écourtée en utilisant des ressources statiques:

<Thickness x:Key="BorderThickness">3</Thickness> 

<BorderyViewbox x:Name="Viewbox"> 
    <Border BorderBrush="Red" SnapsToDevicePixels="True" 
      BorderThickness="{Binding Path=Scale, ElementName=Viewbox, 
        Converter={x:Static BorderyViewbox.ThicknessConverter}, 
        ConverterParameter={StaticResource BorderThickness}}" /> 
</BorderyViewbox> 
Questions connexes