MatrixTransform в комбинация с Width/Height of a Canvas

Когато увеличавам мащаба на чертеж върху платно, имам изискване да показвам ленти за превъртане.
Платното е в ScrollViewer и аз увеличавам ширината/височината на платното, така че лентите за превъртане да се показват (иначе не се появяват).

За да увелича мащаба с коефициент 1,1, използвам този код:

Matrix m = this.LayoutTransform.Value;
if (e.Delta > 0) f = 1.1;
else f = 1.0 / 1.1;
m.Scale(f, f);
this.LayoutTransform = new MatrixTransform(m);
this.Height = this.ActualHeight * f;
this.Width = this.ActualWidth * f;

Оказва се, че платното става твърде голямо. Чертежът се увеличава с 10%, но ширината изглежда става с 20% повече като квадрат от 1,1. Така че използвам Math.Sqrt(f); вместо f.

Може ли някой да обясни защо се държи по този начин?


person Gerard    schedule 04.03.2014    source източник
comment
Изглежда, че прилагате коефициента на мащабиране два пъти, първо чрез LayoutTransform и второ чрез умножаване на Width и Height. Трябва да направите само едно от тях, за предпочитане само LayoutTransform.   -  person Clemens    schedule 04.03.2014
comment
След това лентите за превъртане не се появяват (което е задължително).   -  person Gerard    schedule 04.03.2014


Отговори (1)


Трябва да промените само LayoutTransform на Canvas, както в този опростен пример:

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Canvas Width="1000" Height="1000" Background="Transparent"
            MouseWheel="Canvas_MouseWheel">
        <Canvas.LayoutTransform>
            <MatrixTransform/>
        </Canvas.LayoutTransform>
    </Canvas>
</ScrollViewer>

Манипулаторът на събитие MouseWheel:

private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
    var element = (FrameworkElement)sender;
    var transform = (MatrixTransform)element.LayoutTransform;
    var matrix = transform.Matrix;
    var scale = e.Delta >= 0d ? 1.1 : (1d / 1.1);

    matrix.Scale(scale, scale);
    transform.Matrix = matrix;

    e.Handled = true;
}
person Clemens    schedule 04.03.2014
comment
Работи ли без Width="1000" Height="1000"? Моето платно няма първоначален размер, то пасва на родителския си размер и размерите на чертежа също. - person Gerard; 04.03.2014
comment
Трябва да има първоначален размер, в противен случай ScrollViewer няма смисъл. Можете обаче да зададете първоначалния размер в кода веднага щом е наличен. - person Clemens; 04.03.2014
comment
Още един въпрос: когато нулирам Transform обратно към Identity, лентите за превъртане остават видими, докато първоначално не се виждат (което е добре) и размерът на Canvas не се е променил. - person Gerard; 04.03.2014
comment
Още един въпрос: когато използвате RenderTransform вместо LayoutTransform, лентите за превъртане не се появяват въпреки настройката на Width&Heigth. - person Gerard; 04.03.2014
comment
Първи въпрос: трудно е да се каже, без да видите кода си. Второ: RenderTransform не влияе върху оформлението, но имате нужда от това. Не можете да използвате RenderTransform тук. - person Clemens; 04.03.2014
comment
Възможно ли е може би да комбинирате Render- и LayoutTransform, защото RenderTransform мащабира много по-добре. - person Gerard; 04.03.2014
comment
Не мисля така. Както беше казано по-рано, трябва оформлението да бъде преизчислено, за да актуализирате лентите за превъртане. - person Clemens; 04.03.2014