7 Stimmen

Wie kann man den Bereich der Leinwand in einem ScrollViewer zentriert halten, wenn man hinein- oder herauszoomt und nicht alles im Sichtfenster angezeigt werden kann?

Alle,

Ich habe eine WPF-Anwendung, die eine Leinwand hat, die ich in einem Scroll-Viewer eingewickelt habe. Ich habe einen Schieberegler in der Statusleiste, die der Benutzer zu vergrößern und verkleinern (genau wie Win 7 mspaint) ermöglicht.

Hier ist ein Teil der XAML:

<ScrollViewer Name="Map"
              VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Auto">
    <Canvas x:Name="WallsCanvas" Height="800" Width="1000" ClipToBounds="True">
        <Canvas.LayoutTransform>
            <ScaleTransform x:Name="WallsCanvasScale"
                            ScaleX="1" ScaleY="1" />
        </Canvas.LayoutTransform>
    </Canvas>
</ScrollViewer>

Wenn ich die Ansicht vergrößere und die Bildlaufleisten sichtbar sind, springen die Bildlaufleisten, egal wo sie eingestellt sind, in die Mitte.

Es ist genau so, als ob der Wert der Bildlaufleisten gleich bleibt, aber der Maximalwert steigt.

Was kann ich tun, damit sie ... sagen wir, wenn sie in der unteren rechten Ecke waren, nach dem Vergrößern oder Verkleinern in der unteren rechten Ecke bleiben?

Übrigens, hier ist mein Zoom in und out Code:

private void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    var scales = new []{.125, .25, .5, 1, 2, 4, 8};
    var scale = scales[(int)((Slider) sender).Value];

    ScaleChanged(scale, WallsCanvasScale);
}

private static void ScaleChanged(double scale, ScaleTransform st)
{
    st.ScaleX = scale;
    st.ScaleY = scale;
}

Also, keine Raketenwissenschaft in meinem Code, aber ...

Update-Idee: Wenn ich Zugriff auf den Wert und den Maximalwert der Bildlaufleisten hätte, könnte ich den Prozentsatz zwischen den beiden erhalten und dann nach dem Zoomen (Skalieren) könnte ich den Wert der Bildlaufleiste als Prozentsatz des Maximalwerts wieder anwenden????? Aber wo sind der Wert und der Maximalwert verfügbar?

Für jede Hilfe wären wir dankbar. Ich kann nicht glauben, dass ich der einzige bin, der dieses Problem hat, da MSPaint (die Windows 7-Version) korrekt funktioniert und ich davon ausgehe, dass es eine XAML-App ist.

Hier ist ein Link (http://www.leesaunders.net/examples/zoomexample/zoomexample.zip) auf ein minimal funktionierendes Beispielprojekt (VS 2010). Wenn Sie es ausführen, verschieben Sie einfach die Bildlaufleisten und zoomen Sie eine Ebene, Sie werden das Problem sofort sehen.

3voto

H.B. Punkte 140726

Sie müssen nur die Verschiebung ausgleichen, die sich aus der Skalierung ergibt, da diese von (0,0) ausgeht. Es ist ein bisschen kompliziert, aber hier ist eine Skizze, wie die Methode in Ihrem Beispiel aussehen könnte:

private void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    var slider = (Slider)sender;
    if (!slider.IsLoaded)
    {
        slider.Loaded += (s, le) => SliderValueChanged(sender, e);
        return;
    }

    var scales = new[] { .125, .25, .5, 1, 2, 4, 8 };
    var scale = scales[(int)((Slider)sender).Value];

    // The "+20" are there to account for the scrollbars... i think. Not perfectly accurate.
    var relativeMiddle = new Point((Map.ActualWidth + 20) / 2, (Map.ActualHeight + 20) / 2);
    var oldLocation = CanvasScale.Transform(TemplateCanvas.PointFromScreen(relativeMiddle));

    ScaleChanged(scale, CanvasScale);

    var newLocation = CanvasScale.Transform(TemplateCanvas.PointFromScreen(relativeMiddle));

    var shift = newLocation - oldLocation;

    Map.ScrollToVerticalOffset(Map.VerticalOffset + shift.Y);
    Map.ScrollToHorizontalOffset(Map.HorizontalOffset + shift.X);

    lblScale.Content = scale.ToString("P1").Replace(".0", string.Empty);
}

Die Position des Mittelpunkts wird vor und nach der Skalierung gemessen, um die Verschiebung dieses Punktes zu berechnen, die dann zur aktuellen Bildlaufposition addiert wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X