2012-12-05 66 views
2

我想要一個圖像作爲背景,將統一拉伸。然後我希望我的畫布的尺寸等於均勻拉伸的圖像(我發現的解決方法是在網格內部放置圖像和畫布,並將畫布寬度/高度綁定到圖像的實際高度/寬度)。WPF畫布和放置項目

然後我想有帆布內的項目,將是絕對positioned.But這裏是問題。如果一個項目X爲50和形象是200像素寬度,則其確定。但如果圖像獲得100px寬度項X應該是25.另外我想要一個小規模的變換。有沒有辦法通過綁定來實現這一點? 我是否必須實現我的自定義面板usercontrol,因爲我看不到其他乾淨的解決方案。

回答

3

你當然可以通過綁定實現這一切,但我想,這將是一個更容易和更清潔的,以創建一個派生小組,安排在相對於面板的ActualWidth的和的ActualHeight位置兒童。

派生Panel類可以爲孩子的位置,類似於Canvas.Left和Canvas.Top定義附加屬性,但具有分數值的範圍從0到1

它也可能維持的背景圖像作爲依賴屬性。你會覆蓋OnRender方法來直接繪製此圖像。

小組還可以通過除以例如小數點來計算當前比例因子。它的ActualWidth由圖像的寬度決定。一個合適的ScaleTransform屬性將很容易附加到每個孩子的RenderTransform。

編輯:除了小組的尺寸相對於背景圖像的均勻性,下面可能給你的那個小組中如何實現一個想法:

public class ImagePanel : Panel 
{ 
    public static readonly DependencyProperty LeftProperty = DependencyProperty.RegisterAttached(
     "Left", typeof(double), typeof(ImagePanel), 
     new FrameworkPropertyMetadata(PositionChanged)); 

    public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached(
     "Top", typeof(double), typeof(ImagePanel), 
     new FrameworkPropertyMetadata(PositionChanged)); 

    public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(
     "Image", typeof(ImageSource), typeof(ImagePanel), 
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); 

    private ScaleTransform scaleTransform = new ScaleTransform(); 

    public static double GetLeft(DependencyObject obj) 
    { 
     return (double)obj.GetValue(LeftProperty); 
    } 

    public static void SetLeft(DependencyObject obj, double value) 
    { 
     obj.SetValue(LeftProperty, value); 
    } 

    public static double GetTop(DependencyObject obj) 
    { 
     return (double)obj.GetValue(TopProperty); 
    } 

    public static void SetTop(DependencyObject obj, double value) 
    { 
     obj.SetValue(TopProperty, value); 
    } 

    public ImageSource Image 
    { 
     get { return (ImageSource)GetValue(ImageProperty); } 
     set { SetValue(ImageProperty, value); } 
    } 

    protected override void OnRender(DrawingContext dc) 
    { 
     if (Image != null) 
     { 
      dc.DrawImage(Image, new Rect(0d, 0d, ActualWidth, ActualHeight)); 
     } 

     base.OnRender(dc); 
    } 

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) 
    { 
     base.OnRenderSizeChanged(sizeInfo); 

     if (Image != null) 
     { 
      scaleTransform.ScaleX = sizeInfo.NewSize.Width/Image.Width; 
      scaleTransform.ScaleY = sizeInfo.NewSize.Height/Image.Height; 
     } 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     foreach (UIElement element in InternalChildren) 
     { 
      element.Measure(availableSize); 
     } 

     return new Size(); 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     foreach (UIElement element in InternalChildren) 
     { 
      element.RenderTransform = scaleTransform; 
      ArrangeElement(element, finalSize.Width, finalSize.Height); 
     } 

     return finalSize; 
    } 

    private static void PositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var element = obj as UIElement; 
     var panel = VisualTreeHelper.GetParent(obj) as ImagePanel; 

     if (element != null && panel != null) 
     { 
      ArrangeElement(element, panel.ActualWidth, panel.ActualHeight); 
     } 
    } 

    private static void ArrangeElement(UIElement element, double width, double height) 
    { 
     var left = GetLeft(element); 
     var top = GetLeft(element); 
     var rect = new Rect(new Point(left * width, top * height), element.DesiredSize); 

     element.Arrange(rect); 
    } 
} 
+0

currenlty我使用綁定莫名其妙,但它攪亂了沒有理由的模型。這似乎很有希望。我不知道如何定義附加屬性,但我想我可以弄清楚。 0..1似乎是個好主意,因爲我可以讓用戶定位他想要的元素,而無需在開始時以全尺寸顯示圖像。有沒有辦法緩存圖像?因爲我需要約4-5塊面板。另外,如果我把縮放比例轉換成每個孩子,它會如何處理它的因子?我的意思是綁定或從面板代碼?如果綁定意味着在我的POCO上有一個額外的屬性?謝謝 – GorillaApe

+0

「有沒有緩存圖像的方法」:WPF應該在內存中緩存位圖,否則System.Runtime.Caching.MemoryCache將是一個選項。 「通過綁定或通過面板代碼進行ScaleTransform」:最簡單的方法是簡單地設置每個孩子的RenderTransform屬性(例如,在Panel.ArrangeOverride中),但是當然孩子們當然不能定義他們自己的RenderTransform。綁定到類似'Parent.ScaleTransform'的東西也應該是可能的,沒有任何額外的viewmodel屬性。 – Clemens

+0

謝謝!好吧,似乎它的作品。現在的問題是,使用附加屬性的位置我怎麼可以讓用戶移動它?我用一個拇指,但我應該以某種方式映射到0..1的dX移動不知何故 – GorillaApe