I am using Framework version 4.0,
My problem when Zoom, Canvas should not re-size. or children only zoom IN / OUT?
please suggest me.
Thanks
I have done this before, the solution I found was when ever the zoom-in, make zoom out to the items I want keep the same size.
So, the zoom is a scale transform, then always when the scale transform in the container zoom item increase, you need to apply a decreasing transform to the items (the items you want keep the size). Here I have a sample code of an attached property that you can use later in xaml code:
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
}
}
The inverse converter:
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
}
}
You can use this in styles:
<Style x:Key="PointListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
...
<Setter Property="AttachedProperty:KeepSizeOnZoomBehavior.KeppSizeOnZoom" Value="True"/>
...
Or you can use it directly on visual items:
<Buttom AttachedProperty:KeepSizeOnZoomBehavior.KeppSizeOnZoom="True" .../>
Try this, maybe helps you...
EDIT
The ViewUtil is a simple static class for helping in some manage things, here is the code:
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;
}
}
}