Silverlight智能表单(1)关于控件拖动
前几天闲来无事就在家做sl的智能表单,因为技术有限,各种架构没能设计好,于是-------大家都知道,我拿出自己算是能够称的上功能的东西给大家分享一下。
1.控件在画布上拖动和大小设置。
2.控件从工具箱拖到画布。
3.生成XML。
今天就只写第一个在画布上拖动和设置大小,当时我想的是只做一个拖动的控件(占时叫SizeCtr),然后点击哪个控件,SizeCtr就放到哪个控件上面。
先展示下 SizeCtr 和 运行的效果:
这是两个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;
}
今天就写这么多,以后我会将我做的未完成的智能表单拿出来供大家分享,虽然个人技术能力有限,在设计方面缺陷太大。仅仅供大家一个思考的方法,如果能对你有帮助,拿去用哈哈。。。。