2014-09-22 25 views
1

我有一個Canvas作爲我的應用程序的基礎,它有幾個控件,用戶可以使用它們各自的ManipulationDelta's來移動,旋轉和縮放。在屏幕邊界內限制控制/ UIElement

問題是,用戶可能會意外地將控件移出Canvas或屏幕邊界,同時用手指移動控件。

如何限制這些控件在Canvas內的移動?

回答

2

您可以在WinRT XAML Toolkit中檢查ToolWindow控件和FlickBehavior以獲取靈感。

這是非常基本的整體。如果你不這樣做慣性,可能是這樣的:

if (x < 0) 
    x = 0; 
if (x > _canvas.ActualWidth - this.AssociatedObject.ActualWidth) 
    x = _canvas.ActualWidth - this.AssociatedObject.ActualWidth; 
if (y < 0) 
    y = 0; 
if (y > _canvas.ActualHeight - this.AssociatedObject.ActualHeight) 
    y = _canvas.ActualHeight - this.AssociatedObject.ActualHeight; 

一旦你旋轉或縮放 - 你需要做一些矩陣變換操作,以獲得邊框。幸運的是,該平臺有一些方法可以讓你更容易 - 即TransformToVisual()TransformPoint()方法。我也有一個輔助類,使用en擴展方法,使它更容易 - 檢查出VisualTreeHelperExtensions.GetBoundingRect()

/// <summary> 
/// Gets the bounding rectangle of a given element 
/// relative to a given other element or visual root 
/// if relativeTo is null or not specified. 
/// </summary> 
/// <remarks> 
/// Note that the bounding box is calculated based on the corners of the element relative to itself, 
/// so e.g. a bounding box of a rotated ellipse will be larger than necessary and in general 
/// bounding boxes of elements with transforms applied to them will often be calculated incorrectly. 
/// </remarks> 
/// <param name="dob">The starting element.</param> 
/// <param name="relativeTo">The relative to element.</param> 
/// <returns></returns> 
/// <exception cref="System.InvalidOperationException">Element not in visual tree.</exception> 
public static Rect GetBoundingRect(this FrameworkElement dob, FrameworkElement relativeTo = null) 
{ 
    if (DesignMode.DesignModeEnabled) 
    { 
     return Rect.Empty; 
    } 

    if (relativeTo == null) 
    { 
     relativeTo = Window.Current.Content as FrameworkElement; 
    } 

    if (relativeTo == null) 
    { 
     throw new InvalidOperationException("Element not in visual tree."); 
    } 

    if (dob == relativeTo) 
    { 
     return new Rect(0, 0, relativeTo.ActualWidth, relativeTo.ActualHeight); 
    } 

    var ancestors = dob.GetAncestors().ToArray(); 

    if (!ancestors.Contains(relativeTo)) 
    { 
     throw new InvalidOperationException("Element not in visual tree."); 
    } 

    var topLeft = 
     dob 
      .TransformToVisual(relativeTo) 
      .TransformPoint(new Point()); 
    var topRight = 
     dob 
      .TransformToVisual(relativeTo) 
      .TransformPoint(
       new Point(
        dob.ActualWidth, 
        0)); 
    var bottomLeft = 
     dob 
      .TransformToVisual(relativeTo) 
      .TransformPoint(
       new Point(
        0, 
        dob.ActualHeight)); 
    var bottomRight = 
     dob 
      .TransformToVisual(relativeTo) 
      .TransformPoint(
       new Point(
        dob.ActualWidth, 
        dob.ActualHeight)); 

    var minX = new[] { topLeft.X, topRight.X, bottomLeft.X, bottomRight.X }.Min(); 
    var maxX = new[] { topLeft.X, topRight.X, bottomLeft.X, bottomRight.X }.Max(); 
    var minY = new[] { topLeft.Y, topRight.Y, bottomLeft.Y, bottomRight.Y }.Min(); 
    var maxY = new[] { topLeft.Y, topRight.Y, bottomLeft.Y, bottomRight.Y }.Max(); 

    return new Rect(minX, minY, maxX - minX, maxY - minY); 
} 

一旦你的邊界RECT - 您可以使用它的尺寸,而不是被操縱的對象ActualWidth/ActualHeight和X & y以確定它可以或不可以去。

+0

是的,這是控件與屏幕邊界對齊時的作品。但是,當控件旋轉一個角度時,將'ActualWidth'添加到'x',其中x是左上角的點不會給出右上角的點。 – 2014-09-26 05:16:42

+0

我已經更新了我對這種情況的回答。 – 2014-09-26 15:05:42

+0

這很好! – 2014-09-30 02:44:19