首頁 > 軟體

C# wpf Grid中實現控制元件拖動調整大小的範例程式碼

2022-08-05 14:03:27

前言

在《C# wpf Canvas中實現控制元件動態調整大小》中我們實現了Canvas中的控制元件動態調整大小,由於Grid也是可層疊佈局,在Grid中也是可以實現動態調整大小的。

一、功能說明

8個點方放置在控制元件的8個方位上,通過拖動這些點對控制元件進行拉伸或縮小,示意圖如下:

二、如何實現?

1.繼承Adorner

通過裝飾器的方式新增8個點在控制元件上,這樣既可以不影響控制元件佈局,又可以自由擺放8點控制元件。通過重寫方法,給裝飾新增控制元件。必要的重寫的方法如下面範例所示:

public class GridAdorner : Adorner
{
  //獲取裝飾器的元素個數
  protected override Visual GetVisualChild(int index);
  //指定裝飾器子元素個數
  protected override int VisualChildrenCount{get;}
  //佈局,新增的子元素需要手動佈局。
  protected override Size ArrangeOverride(Size finalSize);      
}

2.使用Thumb

因為Thumb實現拖動比較容易,有相關事件獲取拖動距離。在裝飾器中定義8個Thumb,對應8個方位點。
範例程式碼如下:

//4條邊
Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
//4個角
Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;

初始化

 public GridAdorner(UIElement adornedElement) : base(adornedElement)
 {
     //初始化thumb
     _leftThumb = new Thumb();
     _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
     _leftThumb.VerticalAlignment = VerticalAlignment.Center;
     _leftThumb.Cursor = Cursors.SizeWE;
     //其他略...
}

3.實現拖動邏輯

在Thumb的DragDelta事件可以獲取拖動距離,根據八個方位的不同計算並修改控制元件的大小。

private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
//1.右側點HorizontalChange加寬,右邊距減HorizontalChange
//2.左側點HorizontalChange減寬,左邊距加HorizontalChange
//3.下側點VerticalChange加高,下邊距減VerticalChange
//4.上側點VerticalChange減高,上邊距加VerticalChange
}

三、完整程式碼

程式碼如下:

 public class GridAdorner : Adorner
    {
        //4條邊
        Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
        //4個角
        Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
        //佈局容器,如果不使用佈局容器,則需要給上述8個控制元件佈局,實現和Grid佈局定位是一樣的,會比較繁瑣且意義不大。
        Grid _grid;
        UIElement _adornedElement;
        public GridAdorner(UIElement adornedElement) : base(adornedElement)
        {
            _adornedElement = adornedElement;
            //初始化thumb
            _leftThumb = new Thumb();
            _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftThumb.VerticalAlignment = VerticalAlignment.Center;
            _leftThumb.Cursor = Cursors.SizeWE;
            _topThumb = new Thumb();
            _topThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _topThumb.VerticalAlignment = VerticalAlignment.Top;
            _topThumb.Cursor = Cursors.SizeNS;
            _rightThumb = new Thumb();
            _rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightThumb.VerticalAlignment = VerticalAlignment.Center;
            _rightThumb.Cursor = Cursors.SizeWE;
            _bottomThumb = new Thumb();
            _bottomThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _bottomThumb.Cursor = Cursors.SizeNS;
            _lefTopThumb = new Thumb();
            _lefTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _lefTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _lefTopThumb.Cursor = Cursors.SizeNWSE;
            _rightTopThumb = new Thumb();
            _rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _rightTopThumb.Cursor = Cursors.SizeNESW;
            _rightBottomThumb = new Thumb();
            _rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _rightBottomThumb.Cursor = Cursors.SizeNWSE;
            _leftbottomThumb = new Thumb();
            _leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _leftbottomThumb.Cursor = Cursors.SizeNESW;
            _grid = new Grid();
            _grid.Children.Add(_leftThumb);
            _grid.Children.Add(_topThumb);
            _grid.Children.Add(_rightThumb);
            _grid.Children.Add(_bottomThumb);
            _grid.Children.Add(_lefTopThumb);
            _grid.Children.Add(_rightTopThumb);
            _grid.Children.Add(_rightBottomThumb);
            _grid.Children.Add(_leftbottomThumb);
            AddVisualChild(_grid);
            foreach (Thumb thumb in _grid.Children)
            {
                thumb.Width = 16;
                thumb.Height = 16;
                thumb.Background = Brushes.Green;
                thumb.Template = new ControlTemplate(typeof(Thumb))
                {
                    VisualTree = GetFactory(new SolidColorBrush(Colors.White))
                };
                thumb.DragDelta += Thumb_DragDelta;
            }
        }
        protected override Visual GetVisualChild(int index)
        {
            return _grid;
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return 1;
            }
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            //直接給grid佈局,grid內部的thumb會自動佈局。
            _grid.Arrange(new Rect(new Point(-_leftThumb.Width / 2, -_leftThumb.Height / 2), new Size(finalSize.Width + _leftThumb.Width, finalSize.Height + _leftThumb.Height)));
            return finalSize;
        }
        //拖動邏輯
        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var c = _adornedElement as FrameworkElement;
            var thumb = sender as FrameworkElement;
            double left, top, right, bottom, width, height;
            if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
            {
                right = c.Margin.Right;
                left = c.Margin.Left + e.HorizontalChange;
                width =(double.IsNaN(c.Width)?c.ActualWidth:c.Width)- e.HorizontalChange;
            }
            else
            {
                left = c.Margin.Left;
                right = c.Margin.Right - e.HorizontalChange;
                width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width )+ e.HorizontalChange;
            }

            if (thumb.VerticalAlignment == VerticalAlignment.Top)
            {
                bottom = c.Margin.Bottom;
                top = c.Margin.Top + e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) - e.VerticalChange;

            }
            else
            {
                top = c.Margin.Top;
                bottom = c.Margin.Bottom - e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height )+ e.VerticalChange;
            }
            if (thumb.HorizontalAlignment != HorizontalAlignment.Center)
            {
                if (width >= 0)
                {
                    c.Margin = new Thickness(left, c.Margin.Top, right, c.Margin.Bottom);
                    c.Width = width;
                }
            }
            if (thumb.VerticalAlignment != VerticalAlignment.Center)
            {
                if (height >= 0)
                {
                    c.Margin = new Thickness(c.Margin.Left, top, c.Margin.Right, bottom);
                    c.Height = height;
                }
            }
        }
        //thumb的樣式
        FrameworkElementFactory GetFactory(Brush back)
        {
            var fef = new FrameworkElementFactory(typeof(Ellipse));
            fef.SetValue(Ellipse.FillProperty, back);
            fef.SetValue(Ellipse.StrokeProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")));
            fef.SetValue(Ellipse.StrokeThicknessProperty, (double)2);
            return fef;
        }
    }

四、使用範例

範例程式碼如下:

xml

<Grid>
    <Border  x:Name="border"  Width="200" Height="200"  Background="Gray" ></Border>
</Grid>

在視窗或控制元件的Loaded事件中新增裝飾器:
cs

private void window_Loaded(object sender, RoutedEventArgs e)
{
    var layer = AdornerLayer.GetAdornerLayer(border);
    layer.Add(new GridAdorner(border));
}

效果預覽:

總結

以上就是今天要講的內容,本文講述了Grid中控制元件縮放的方法與實現,與Canvas的實現大部分是相同的,唯一的區別就是設定Margin,總得來說還是比較容易實現的,最終呈現的效果也是比較不錯的。

到此這篇關於C# wpf Grid中實現控制元件拖動調整大小的範例程式碼的文章就介紹到這了,更多相關C# wpf Grid拖動調整大小內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com