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.打了个漫长的电话就不知道该说些什么了,今天周五,各位大侠玩的开心。

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

你可能感兴趣的:(silverlight)