Silverlight智能表单(2)从工具箱到画板

从工具箱到画板,让我想起来从百草园到三味书屋,虽然驴嘴不对马口,但是没有下文了。

控件从工具箱到画板的拖动让我想到了tookit中DragDropTarget控件,工具箱好说用ListBox或者TreeView,画板就不知道怎么搞了,于是决定自己做DragDrop。

先贴张图片:

捕获

 

左侧的是一个listbox,右侧红色的是Canvas。创建一个类库DragDropLibrary(这个名不知道好不好听)。

点击左侧的ListBox,然后移动鼠标到右侧红色部分,松开鼠标控件就放到松开的位置,思路就这么简单。

ListBox的Xaml:(Controls = new string[3] { "TextBox", "Button", "TextBlock" };这个是给ListBox的数据,测试。。。)

<ListBox x:Name="ToolBox" ItemsSource="{Binding Controls,Mode=OneTime}">
    <ListBox.ItemTemplate>
        <DataTemplate >
            <TextBlock Text="{Binding}" MouseLeftButtonDown="OnListBoxItemMouseLeftButtonDown" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Item就一个TextBlock,我们要注册MouseLeftButtonDown事件。

在DragDropLibrary中添加一个类:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DragDropLibrary
{
    public static class DragDropManage
    {
        private static Panel _root, _board;
        //Drop
        public delegate void Drop(DragDropEventArgs target);
        private static Drop _OnDrag;
        private static DragDropEventArgs eveArgs;
        
        //鼠标拖动时跟随效果
        private static Image _MouseEffert;

        /// <summary>
        /// 拖动之前调用
        /// </summary>
        /// <param name="root">根Panel(Children中包含工具箱和画板)</param>
        /// <param name="board">画板</param>
        public static void Register(Panel root, Panel board)
        {
            _root = root;
            _board = board;
            if (_root is Grid)
            {
                Grid.SetColumnSpan(_MouseEffert, (_root as Grid).ColumnDefinitions.Count+1);
                Grid.SetRowSpan(_MouseEffert, (_root as Grid).RowDefinitions.Count+1);
            }
        }

        static DragDropManage()
        {
            _MouseEffert = new Image();
        }

        public static void BeginDrag(object sender, MouseButtonEventArgs e, Drop drop)
        {
            FrameworkElement target = sender as FrameworkElement;
            WriteableBitmap bitmap = new WriteableBitmap(target, new TranslateTransform());
            _MouseEffert.Source =bitmap;
            _MouseEffert.Height = bitmap.PixelHeight;
            _MouseEffert.Width = bitmap.PixelWidth;
            _root.Children.Add(_MouseEffert);
            Point position = e.GetPosition(_root);
            _MouseEffert.Margin = new Thickness(position.X, position.Y, 0, 0);

            _MouseEffert.HorizontalAlignment = HorizontalAlignment.Left;
            _MouseEffert.VerticalAlignment = VerticalAlignment.Top;
            _MouseEffert.CaptureMouse();
            eveArgs = new DragDropEventArgs(target);

            _OnDrag = drop;
            _root.MouseMove += OnRootMouseMove;
            _root.MouseLeftButtonUp += OnRootMouseLeftButtonUp;
        }

        private static void Clear()
        {
            _root.MouseMove -= OnRootMouseMove;
            _root.MouseLeftButtonUp -= OnRootMouseLeftButtonUp;
            _root.Children.Remove(_MouseEffert);
            _OnDrag = null;
            eveArgs = null;
        }

        private static void OnRootMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            eveArgs.Position = e.GetPosition(_board);
            _OnDrag(eveArgs);
            Clear();
        }

        private static void OnRootMouseMove(object sender, MouseEventArgs e)
        {
            Point position = e.GetPosition(_root);
            _MouseEffert.Margin = new Thickness(position.X, position.Y, 0, 0);

            Point currentPosition = e.GetPosition(_board);
            if (currentPosition.X > 0 && currentPosition.X < _board.ActualWidth
                && currentPosition.Y > 0 && currentPosition.Y < _board.ActualHeight)
            {
                eveArgs.Accept = true;
            }
            else
            {
                eveArgs.Accept = false;
            }
        }
    }
}
using System;
using System.Windows;

namespace DragDropLibrary
{
    public class DragDropEventArgs : EventArgs
    {
        public bool Accept { get; set; }

        public Point Position { get; internal set; }

        public FrameworkElement Target { get; private set; }

        public DragDropEventArgs(FrameworkElement target)
        {
            Target = target;
            Position = new Point(0, 0);
        }
    }
}

 

这个EventArgs类也一并贴出。

DragDropManage我做成了静态类,我的电脑只有一个鼠标,而且我也没有多点触控的装备,不知道多点触控能不能同时托两个或者更多控件。

在最最最开始,我们需要初始化DragDropLibrary.DragDropManage.Register(LayoutRoot, BoardCanvas);

LayoutRoot这个都知道,就是程序的根容器,BoardCanvas就是上面说的红色的Canvas。

TextBlock鼠标点击事件,这时我们就开始拖动了。Drop1是一个方法,用来当我们松开鼠标时的回调方法。

private void OnListBoxItemMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
            DragDropLibrary.DragDropManage.BeginDrag(sender, e, Drop1);
}

 

public void Drag1(DragDropLibrary.DragDropEventArgs target)
{
	if (target.Accept)
	{
		string name = (target.Target as TextBlock).Text;
		FrameworkElement element = null;
		
		Type type = GetTypeFromString(name);
		if (type != null)
		{
		    element = Activator.CreateInstance(type) as FrameworkElement;

		    if (target.Position != null)
		    {
		        Canvas.SetLeft(element, target.Position.X);
		        Canvas.SetTop(element, target.Position.Y);
		    }

		    element.Width = 80;
		    element.Height = 40;

		    BoardCanvas.Children.Add(element);
		}
	}
}
private Type GetTypeFromString(string typeName)
{
	Type type = null;
	typeName = "System.Windows.Controls." + typeName;
	Assembly assembly = Assembly.Load("System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e");

	type = assembly.GetType(typeName);
	return type;
}

 

 

在Drop1中Target是ListBox中的TextBlock所以直接转了。

几点说明:

1.DragDropEventArgs中Accept是用来说明,松开鼠标时,当前鼠标的位置是不是落在Canvas中。Position指示当前位置

2.DragDropEventArgs中Target是鼠标点击时的控件。

3.生成控件我是根据名称和程序集,这两个东西获取的,一开始我设想的就是把所有的控件存到Xml文件中,包括他的中文名,全名,以及程序集,这样ListBox中的控件就可以反射出来了。

4.拖动时要在根容器中注册MouseMove事件以及MouseDown。

5.打了个漫长的电话就不知道该说些什么了,今天周五,各位大侠玩的开心。

本人菜鸟一个,刚刚从学校步入社会,还有很多地方需要向大家学习。开博也是为了和大家更好的交流,将自己的小小的代码拿来让大家批评指正。。。。

posted @ 2011-01-21 22:04  Honker Snow  阅读(965)  评论(2编辑  收藏  举报