WPF缩放没有画布大小更改

时间:2013-10-25 11:23:12

标签: wpf canvas deepzoom

我使用的是Framework 4.0版,

我在Zoom,Canvas时不应该重新调整大小的问题。或儿童只能缩放IN / OUT?

请建议我。

由于

2 个答案:

答案 0 :(得分:2)

之前我已经完成了这个,我找到的解决方案是放大时,缩小我想要的项目保持相同的大小。

因此,缩放是一种缩放变换,然后总是当容器缩放项目中的缩放变换增加时,您需要对项目应用减少变换(您想要保留大小的项目)。 这里我有一个附加属性的示例代码,稍后您可以在xaml代码中使用它:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using Cepha.View.Converter;
using Cepha.View.Util;
using Microsoft.Practices.ServiceLocation;
using WPFExtensions.Controls;

namespace Cepha.View.AttachedProperty
{
    public static class KeepSizeOnZoomBehavior
    {
        #region KeppSizeOnZoom

    public static bool GetKeppSizeOnZoom(DependencyObject obj)
    {
        return (bool) obj.GetValue(KeppSizeOnZoomProperty);
    }

    public static void SetKeppSizeOnZoom(DependencyObject obj, bool value)
    {
        obj.SetValue(KeppSizeOnZoomProperty, value);
    }

    // Using a DependencyProperty as the backing store for KeppSizeOnZoom.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty KeppSizeOnZoomProperty =
        DependencyProperty.RegisterAttached("KeppSizeOnZoom", typeof (bool), typeof (KeepSizeOnZoomBehavior),
                                            new PropertyMetadata(false, OnKeepSizeOnZoomPropertyChanged));

    private static void OnKeepSizeOnZoomPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var uiElement = d as UIElement;
        if (uiElement == null)
            return;

        if ((bool)e.NewValue)
        {

            var zoomContentPresenter = ViewUtils.GetParent(d, p => p is ZoomContentPresenter) as ZoomContentPresenter;
            if (zoomContentPresenter == null)
                return;
            if (zoomContentPresenter.RenderTransform == null || !(zoomContentPresenter.RenderTransform is TransformGroup))
                return;

            var sourceScaleTransform =
                (zoomContentPresenter.RenderTransform as TransformGroup).Children.FirstOrDefault(
                    c => c is ScaleTransform) as ScaleTransform;

            if (sourceScaleTransform == null)
                return;



            if (uiElement.RenderTransform == null || !(uiElement.RenderTransform is TransformGroup))
            {
                uiElement.RenderTransform = new TransformGroup();
            }
            var scaleTransform =
                (uiElement.RenderTransform as TransformGroup).Children.FirstOrDefault(c => c is ScaleTransform) as
                ScaleTransform;


            var inverseConverter = ServiceLocator.Current.GetInstance<InverseConverter>();

            if (scaleTransform == null)
            {
                scaleTransform =
                    new ScaleTransform(
                        (double) inverseConverter.Convert(sourceScaleTransform.ScaleX, typeof (double), null, null),
                        (double) inverseConverter.Convert(sourceScaleTransform.ScaleY, typeof (double), null, null), 0,
                        0);
                (uiElement.RenderTransform as TransformGroup).Children.Add(scaleTransform);
            }

            BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleXProperty,
                                         new Binding("ScaleX")
                                             {Source = sourceScaleTransform, Converter = inverseConverter});
            BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleYProperty,
                                         new Binding("ScaleY")
                                             {Source = sourceScaleTransform, Converter = inverseConverter});
            if (d is FrameworkElement)
            {
                (d as FrameworkElement).Unloaded += OnElementUnloaded;
            }
        }
        else
        {
            ClearScaleYXBinding(uiElement);
        }
    }

    private static void OnElementUnloaded(object sender, RoutedEventArgs e)
    {
        var uiElement = sender as UIElement;
        if (uiElement == null)
            return;
        ClearScaleYXBinding(uiElement);
        ((FrameworkElement) sender).Unloaded -= OnElementUnloaded;
    }

    private static void ClearScaleYXBinding(UIElement uiElement)
    {
        if (!(uiElement.RenderTransform is TransformGroup))
            return;
        var scaleTransform =
            (uiElement.RenderTransform as TransformGroup).Children.FirstOrDefault(c => c is ScaleTransform) as
            ScaleTransform;
        if (scaleTransform == null)
            return;
        BindingOperations.ClearBinding(scaleTransform, ScaleTransform.ScaleXProperty);
        BindingOperations.ClearBinding(scaleTransform, ScaleTransform.ScaleYProperty);
    }

    #endregion
}
}

逆转换器:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Data;

namespace Cepha.View.Converter
{
    public class InverseConverter:IValueConverter
    {
        #region Implementation of IValueConverter

    /// <summary>
    /// Converts a value. 
    /// </summary>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    /// <param name="value">The value produced by the binding source.</param><param name="targetType">The type of the binding target property.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double)
            return 1/(double) value;
        return 1/(float) value;
    }

    /// <summary>
    /// Converts a value. 
    /// </summary>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    /// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double)
            return 1 / (double)value;
        return 1 / (float)value;
    }

    #endregion
}
}

您可以在样式中使用它:

<Style x:Key="PointListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" Value="Transparent"/>
        ...
        <Setter Property="AttachedProperty:KeepSizeOnZoomBehavior.KeppSizeOnZoom" Value="True"/>
...

或者您可以直接在视觉项目上使用它:

<Buttom AttachedProperty:KeepSizeOnZoomBehavior.KeppSizeOnZoom="True" .../>

试试这个,也许会帮助你......


修改


ViewUtil是一个简单的静态类,用于帮助管理一些东西,这里是代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;

namespace Cepha.View.Util
{
    public static class ViewUtils
    {
        public static bool AnyParent(DependencyObject item, Func<DependencyObject, bool> condition)
        {
            if (item == null)
                return false;

            var logicalParent = LogicalTreeHelper.GetParent(item);
            var visualParent = VisualTreeHelper.GetParent(item);

            return condition(item) || AnyParent(visualParent, condition);
        }

        public static DependencyObject GetParent(DependencyObject item, Func<DependencyObject, bool> condition)
        {
            if (item == null)
                return null;

            var logicalParent = LogicalTreeHelper.GetParent(item);
            var visualParent = VisualTreeHelper.GetParent(item);

            return condition(item) ? item : GetParent(visualParent, condition);
        }

        public static DependencyObject GetVisualChild(DependencyObject item, Func<DependencyObject, bool> condition)
        {
            if (item == null)
                return null;

            var q = new Queue<DependencyObject>();
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(item); i++)
            {
                var t = VisualTreeHelper.GetChild(item, i);
                if (condition(t))
                    return t;
                q.Enqueue(t);
            }

            while (q.Count > 0)
            {
                var subchild = q.Dequeue();
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(subchild); i++)
                {
                    var t = VisualTreeHelper.GetChild(subchild, i);
                    if (condition(t))
                        return t;
                    q.Enqueue(t);
                }
            }
            return null;
        }

        public static DependencyObject GetLogicalChild(DependencyObject item, Func<DependencyObject, bool> condition)
        {
            if (item == null)
                return null;

            var q = new Queue<DependencyObject>();
            foreach (var w in LogicalTreeHelper.GetChildren(item))
            {
                var t = w as DependencyObject;
                if (condition(t))
                    return t;
                q.Enqueue(t);
            }

            while (q.Count > 0)
            {
                var subchild = q.Dequeue();
                foreach (var w in LogicalTreeHelper.GetChildren(subchild))
                {
                    var t = w as DependencyObject;
                    if (condition(t))
                        return t;
                    q.Enqueue(t);
                }
            }
            return null;
        }
    }
}

答案 1 :(得分:0)

ScaleTransform个实例分配给RenderTransform的{​​{1}}媒体资源。较小的值'缩放',大值'缩放'。

如果您要使用画布的Canvas属性,则大小会发生变化。

对微软的转换进行了一些简单的阅读:http://msdn.microsoft.com/en-us/library/ms750596.aspx