Silverlight智能表单(1)关于控件拖动

前几天闲来无事就在家做sl的智能表单,因为技术有限,各种架构没能设计好,于是-------大家都知道,我拿出自己算是能够称的上功能的东西给大家分享一下。

1.控件在画布上拖动和大小设置。

2.控件从工具箱拖到画布。

3.生成XML。

今天就只写第一个在画布上拖动和设置大小,当时我想的是只做一个拖动的控件(占时叫SizeCtr),然后点击哪个控件,SizeCtr就放到哪个控件上面。

先展示下  SizeCtr  和  运行的效果:

sizectr2

 

这是两个Button,其中一个被选中。SizeCtr在边上有8个小锚点(Rectangle),还有中间一个大的框框(Border)

展示下Xaml

<UserControl x:Class="ITLight.Controls.SizeCtr"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="78" d:DesignWidth="216">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.Resources>
            <Style TargetType="Rectangle">
                <Setter Property="Height" Value="4" />
                <Setter Property="Width" Value="4" />
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Stroke" Value="Black" />
                <Setter Property="StrokeThickness" Value="1" />
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="4" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="4" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="4" />
        </Grid.ColumnDefinitions>
        <Border Name="SizeBorder" Grid.Row="1" Grid.Column="1" BorderBrush="Black" BorderThickness="1" Background="#1000" Cursor="Hand" />
        <Rectangle Grid.Row="0" Grid.Column="0" />
        <Rectangle Grid.Row="0" Grid.Column="1"/>
        <Rectangle Grid.Row="0" Grid.Column="2" />

        <Rectangle Grid.Row="1" Grid.Column="0" />
        <Rectangle Grid.Row="1" Grid.Column="2" />

        <Rectangle Grid.Row="2" Grid.Column="0" />
        <Rectangle Grid.Row="2" Grid.Column="1" />
        <Rectangle Grid.Row="2" Grid.Column="2" />
    </Grid>
</UserControl>

还有CS文件:

    public partial class SizeCtr : UserControl
    {
        public SizeCtr()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(OnSizeCtrLoaded);
        }

        private void OnSizeCtrLoaded(object sender, RoutedEventArgs e)
        {
            this.Loaded -= new RoutedEventHandler(OnSizeCtrLoaded);
            UIElementCollection rects = LayoutRoot.Children;
            foreach (var item in rects)
            {
                if (item is Rectangle)
                {
                    Rectangle rect = item as Rectangle;
                    rect.MouseLeftButtonDown += new MouseButtonEventHandler(OnRectMouseLeftButtonDown);
                    rect.MouseLeftButtonUp += new MouseButtonEventHandler(OnRectMouseLeftButtonUp);
                    rect.MouseMove += new MouseEventHandler(OnRectMouseMove);
                    int row = Grid.GetRow(rect);
                    int col = Grid.GetColumn(rect);
                    if (row == 1)
                    {
                        rect.Cursor = Cursors.SizeWE;
                    }
                    else if (col == 1)
                    {
                        rect.Cursor = Cursors.SizeNS;
                    }
                    else if (row == col)
                    {
                        rect.Cursor = Cursors.SizeNWSE;
                    }
                    else
                    {
                        rect.Cursor = Cursors.SizeNESW;
                    }
                }
                SizeBorder.MouseLeftButtonDown += new MouseButtonEventHandler(SizeBorder_MouseLeftButtonDown);
                SizeBorder.MouseLeftButtonUp += new MouseButtonEventHandler(SizeBorder_MouseLeftButtonUp);
                SizeBorder.MouseMove += new MouseEventHandler(SizeBorder_MouseMove);
            }
        }

        private FrameworkElement m_Target;

        public FrameworkElement Target
        {
            get { return m_Target; }
            set
            {

                if (m_Target != value)
                {
                    m_Target = value;
                    if (value != null)
                    {
                        SizeBorder.Height = m_Target.Height;
                        SizeBorder.Width = m_Target.Width;
                        Canvas.SetLeft(this as FrameworkElement, Canvas.GetLeft(m_Target) - 4);
                        Canvas.SetTop(this as FrameworkElement, Canvas.GetTop(m_Target) - 4);
                        this.Visibility = System.Windows.Visibility.Visible;
                    }
                    else
                    {
                        this.Visibility = System.Windows.Visibility.Collapsed;
                    }
                }
            }
        }

        #region Move
        bool canMove;
        private void SizeBorder_MouseMove(object sender, MouseEventArgs e)
        {
            if (canMove)
            {
                Point newPosition = e.GetPosition(null);
                double height = newPosition.Y - mousePosition.Y;
                double width = newPosition.X - mousePosition.X;
                Canvas.SetTop(this as FrameworkElement, Canvas.GetTop(this as FrameworkElement) + height);
                Canvas.SetLeft(this as FrameworkElement, Canvas.GetLeft(this as FrameworkElement) + width);
                if (m_Target != null)
                {
                    Canvas.SetTop(m_Target, Canvas.GetTop(m_Target) + height);
                    Canvas.SetLeft(m_Target, Canvas.GetLeft(m_Target) + width);
                }
                mousePosition = newPosition;
            }
        }

        private void SizeBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            canMove = false;
            (sender as FrameworkElement).ReleaseMouseCapture();
            //this.ReleaseMouseCapture();
        }

        private void SizeBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            canMove = true;
            mousePosition = e.GetPosition(null);
            (sender as FrameworkElement).CaptureMouse();
            //this.ReleaseMouseCapture();
        }

        #endregion

        #region Size
        private bool canSize;
        Point mousePosition;
        private void OnRectMouseMove(object sender, MouseEventArgs e)
        {
            if (canSize)
            {
                Rectangle rect = sender as Rectangle;
                int row = Grid.GetRow(rect);
                int col = Grid.GetColumn(rect);
                Point newPoint = e.GetPosition(null);
                double width = (newPoint.X - mousePosition.X) * (col - 1);
                double height = (newPoint.Y - mousePosition.Y) * (row - 1);
                SizeBorder.Width += width;
                SizeBorder.Height += height;
                if (m_Target != null)
                {
                    m_Target.Height += height;
                    m_Target.Width += width;
                }
                if (row < 1)
                {
                    Canvas.SetTop(this as FrameworkElement, Canvas.GetTop(this as FrameworkElement) - height);
                    if (m_Target != null)
                    {
                        Canvas.SetTop(m_Target, Canvas.GetTop(m_Target) - height);
                    }
                }
                if (col < 1)
                {
                    Canvas.SetLeft(this as FrameworkElement, Canvas.GetLeft(this as FrameworkElement) - width);
                    if (m_Target != null)
                    {
                        Canvas.SetLeft(m_Target, Canvas.GetLeft(m_Target) - width);
                    }
                }
                mousePosition = newPoint;
            }
        }

        private void OnRectMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            canSize = false;
            (sender as Rectangle).ReleaseMouseCapture();
            //this.ReleaseMouseCapture();
        }

        private void OnRectMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            canSize = true;
            mousePosition = e.GetPosition(null);
            (sender as Rectangle).CaptureMouse();
            //this.CaptureMouse();
        }

        #endregion
    }

代码几乎仔细看看都能看明白有几点说明:

1.在设置锚点的鼠标状态时以及改变大小时稍微动了点脑子很easy。。

2.Target属性就是设置当前的选中控件,如果是null的话就将他隐藏掉。

3.一点重要的说明,控件的容器必须是Canvas,SizeCtr也必须是画布Canvas的成员之一而且是最后一个,不然就不能保证在最上面。

4.中间的Border也设置了颜色,透明度设为最低,如果设成不透明的。。。。自己试试(呵呵)。

5.Canvas上要注册的事件MouseLeftButtonUp以及GotFocus,注册一个的话可能不能实现所有的控件的选中。

6.这点说明下,ComboBox选中时会下拉,所以加一句这个,让他不下拉。(哦,忘记了Xaml中能不能设置IsDropDownOpen ,如果能设直接设置成false就可以了,我不测试了。)

            if (e.OriginalSource is ComboBox)
            {
                (e.OriginalSource as ComboBox).IsDropDownOpen = false;
            }

今天就写这么多,以后我会将我做的未完成的智能表单拿出来供大家分享,虽然个人技术能力有限,在设计方面缺陷太大。仅仅供大家一个思考的方法,如果能对你有帮助,拿去用哈哈。。。。

posted @ 2011-01-20 23:33  Honker Snow  阅读(2724)  评论(19编辑  收藏  举报