WPF 在Canvas拖動多個控件的獨立移動的具體實現

寫這篇文章的理由:

觸發機制——單個功能點用時一個工作日的核心代碼實現

具體需求

在Canvas畫布上動態添加可移動的標籤(就是實現截圖功能的文本備註功能)。

主要說移動多個控件功能,在網上找的移動功能都只支持一個文本的移動或者是多個控件同時移動,沒有找到能夠獨立移動的,在此之上我做了一些改進,支持多個文本移動。

UI代碼:

<Grid>
        <Canvas x:Name="canvas1">
            <TextBlock Text="AAA" x:Name="text"></TextBlock>
            <TextBlock Text="BBB" x:Name="text1" Canvas.Left="100"></TextBlock>
        </Canvas>
    </Grid>

後臺實現主要利用了3個事件,TextBlock的MouseLeftButtonDown,Canvas的MouseLeftButtonUp和Canvas的MouseMove

使用一個類變量的移動標誌去控制滑動的開始和結束:

使用一個類變量去保存當前移動的是哪個文本:

//移動標誌
        bool isMoving = false;
//保存當前移動的是哪個文本
TextBlock currentText;

使用TextBlock 的Tag屬性去保存文本移動時需要保存的值;

1.點擊文本時 文本當前的座標值(startMovePosition);

2.文本移動的長度座標值(TotalTranslate);

3.文本最終顯示的座標值(TempTranslate);

爲什麼要用TextBlock的Tag屬性去保存文本移動時需要保存的值呢?

因爲每一個文本移動時都是獨立在移動的,不能因爲這個文本移動而干擾到另外一個文本;而Tag的類型是Object,剛好可以保存我自定義的類型,能夠實現每一個控件獨立移動的核心就是這個tag屬性所保存的值。

TextBlockTag類:

public class TextBlockTag
    {
        public TextBlockTag()
        {
            TotalTranslate = new TranslateTransform();
            TempTranslate = new TranslateTransform();
        }
        public TranslateTransform TotalTranslate { get; set; }
        public TranslateTransform TempTranslate { get; set; }

        public Point startMovePosition { get; set; }
    }

構造函數:

public MainWindow()
        {
            InitializeComponent();
            text.MouseLeftButtonDown += Canvas1_MouseLeftButtonDown;
            text1.MouseLeftButtonDown += Canvas1_MouseLeftButtonDown;
            text.Tag = new TextBlockTag();
            text1.Tag = new TextBlockTag();
            canvas1.MouseLeftButtonUp += Canvas1_MouseLeftButtonUp;
            canvas1.MouseMove += Canvas1_MouseMove;
            canvas1.Focusable = true;//重要:默認條件下不接收鼠標事件
            canvas1.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            canvas1.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
        }

TextBlock的MouseLeftButtonDown事件:

private void Canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var text = sender as TextBlock;
            if (currentText != text)
            {
                currentText = new TextBlock();
                currentText = text;
            }
            (currentText.Tag as TextBlockTag).startMovePosition = e.GetPosition(canvas1);
            isMoving = true;
        }

Canvas的MouseLeftButtonUp事件:

private void Canvas1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (currentText == null)
                return;
            isMoving = false;
            Point endMovePosition = e.GetPosition(canvas1);

            //爲了避免跳躍式的變換,單次有效變化 累加入 totalTranslate中。
            (currentText.Tag as TextBlockTag).TotalTranslate.X += (endMovePosition.X - (currentText.Tag as TextBlockTag).startMovePosition.X);
            (currentText.Tag as TextBlockTag).TotalTranslate.Y += (endMovePosition.Y - (currentText.Tag as TextBlockTag).startMovePosition.Y);
            currentText = null;
        }

Canvas的MouseMove事件:

private void Canvas1_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMoving && e.LeftButton == MouseButtonState.Pressed)
            {
                Point currentMousePosition = e.GetPosition(canvas1);//當前鼠標位置

                Point deltaPt = new Point(0, 0);
                deltaPt.X = (currentMousePosition.X - (currentText.Tag as TextBlockTag).startMovePosition.X);
                deltaPt.Y = (currentMousePosition.Y - (currentText.Tag as TextBlockTag).startMovePosition.Y);

                (currentText.Tag as TextBlockTag).TempTranslate.X = (currentText.Tag as TextBlockTag).TotalTranslate.X + deltaPt.X;
                (currentText.Tag as TextBlockTag).TempTranslate.Y = (currentText.Tag as TextBlockTag).TotalTranslate.Y + deltaPt.Y;
                TransformGroup tfGroup = new TransformGroup();
                tfGroup.Children.Add((currentText.Tag as TextBlockTag).TempTranslate);
                currentText.RenderTransform = tfGroup;
            }
        }

文本移動功能就可以實現了,至於文本添加功能,指哪打哪,就不細說了很簡單,要是想知道完整功能的實現可以私信我。 

最後

這個功能的實現,只是我基於網上的思路改進的,要是你們有什麼其他更簡單的實現思路,麻煩評論說一說,我們共同學習,共同進步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章