曾经总认为动态布局是个非常麻烦的问题。是个非常须要功力的问题。可是貌似在.NET中。在WPF中却不是那么的麻烦。
以下介绍我如今实现的一个动态布局的实例。
由于有需求。所以困难得克服!而我们的需求表名,不同的用户须要的界面元素是不一样的,我们总不能每次都去改动代码吧!所以,须要完毕动态布局。
这里主要完毕这样一个功能:
1、动态画线
2、动态new控件
3、线和控件都是可拖拽并任意放置位置的
4、线和控件是可删除的
5、控件是可绑定属性和事件的
要完毕这种功能,我们首先得定义三个鼠标事件,即:左键down、move、up,右键删除(不能仅仅添加不删除啊)。
比如我要画一条线。那么左键down的时候,我就须要记录当前鼠标的位置。
左键down而且move的时候,要实时显示画出来的线。左键已经down而且左键up的时候记录位置而且完毕画线。
就是这样一个过程我们就完毕了动态画一条线。
动态生成控件就相对简单了,有了线,有了控件,连在一起,不就完毕布局了吗?当然是要把位置记录下来的。
代码上:
void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { //true表示当前是拖拽模式 if (currentPattern == "0") { //推断是否选的是主窗口 if (e.Source == mainCanvas) { } else { _isDown = true; _startPoint = e.GetPosition(mainCanvas); _originalElement = e.Source as UIElement; } } else if (currentPattern == "1") { _isDragging = true; Canvas board = sender as Canvas; _startPoint = e.GetPosition(board); insertShape = CreateShape(); insertShape.Opacity = opacity / 2; Canvas.SetLeft(insertShape, e.GetPosition(board).X); //插入线条的起点x1/y1 Canvas.SetTop(insertShape, e.GetPosition(board).Y); board.Children.Add(insertShape); board.RegisterName(insertShape.Name, insertShape); } } void Canvas_PreviewMouseMove(object sender, MouseEventArgs e) { //true表示当前是拖拽模式 if (currentPattern == "0") { if (_isDown) { //假设没有拖拽或者超出了界面 if ((_isDragging == false) && ((Math.Abs(e.GetPosition(mainCanvas).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(e.GetPosition(mainCanvas).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance))) { _isDragging = true; _originalLeft = Canvas.GetLeft(_originalElement); //获得原元素的位置 _originalTop = Canvas.GetTop(_originalElement); _overlayElement = new Rectangle() { Width = _originalElement.RenderSize.Width, Height = _originalElement.RenderSize.Height, Fill = new VisualBrush(_originalElement), Opacity = 0.8 //阴影的不透明性 }; Canvas.SetLeft(_overlayElement, _originalLeft); Canvas.SetTop(_overlayElement, _originalTop); mainCanvas.Children.Add(_overlayElement); } //假设正在移动中,显示实时位置 if (_isDragging) { Point CurrentPosition = Mouse.GetPosition(mainCanvas); //设置浮动对象的位置 Canvas.SetLeft(_overlayElement, _originalLeft + CurrentPosition.X - _startPoint.X); Canvas.SetTop(_overlayElement, _originalTop + CurrentPosition.Y - _startPoint.Y); } } } else if (currentPattern == "1") { Canvas board = sender as Canvas; if (_isDragging && insertShape != null) { if (insertShape is Line) { (insertShape as Line).X1 = 0; (insertShape as Line).X2 = e.GetPosition(board).X - _startPoint.X; //设置线条的X1/Y1/X2/Y2 (insertShape as Line).Y1 = 0; (insertShape as Line).Y2 = e.GetPosition(board).Y - _startPoint.Y; } } } } void Canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { //true表示当前是拖拽模式 if (currentPattern == "0") { if (_isDown) { if (_isDragging) { //将阴影位置设置为当前 Canvas.SetLeft(_originalElement, Canvas.GetLeft(_overlayElement)); Canvas.SetTop(_originalElement, Canvas.GetTop(_overlayElement)); Point _positionInOverlayElement = Mouse.GetPosition(_overlayElement); mainCanvas.Children.Remove(_overlayElement); _overlayElement = null; } //将移动标识设置为 false _isDragging = false; _isDown = false; } } else if (currentPattern == "1") { //假设是画线模式,则将拖拽设置为false,将透明度还原 _isDragging = false; if (insertShape != null) insertShape.Opacity = opacity; } }
有了这三个基本的事件,你就能够非常轻松的完毕动态布局了。怎样保存的呢?我是把各个控件的位置放在了数据库中,载入的时候将位置信息读出来。
private void btnSave_Click(object sender, RoutedEventArgs e) { //遍历全部的界面控件,拿到他们的位置信息。保存。List<A> listAConfig = new List<A>(); //获得界面上全部的Line元素 List<Line> listLine = GetElementFormUI.GetChildObjects<Line>(mainCanvas); for (int i = 0; i < listLine.Count; i++) { Line l = listLine[i] ; A enAConfig = new A(); enAConfig .S_ID = DateTime.Now.ToFileTime().ToString(); enAConfig .S_NAME = l.Name; enAConfig .S_SHAPETYPE = "Line"; enAConfig .I_LEFT =decimal.Parse(Canvas.GetLeft(l as UIElement).ToString()); enAConfig .I_TOP = decimal.Parse(Canvas.GetTop(l as UIElement).ToString()); enAConfig .I_X2 = decimal.Parse(l.X2.ToString()); enAConfig .I_Y2 = decimal.Parse(l.Y2.ToString()); listAConfig.Add(enAConfig ); } //推断是否保存成功 if (ServiceFactory.GetAConifgService().AddAConfig(listAConfig)) { MessageBox.Show("保存成功!", "恭喜!", MessageBoxButton.OK); } else { MessageBox.Show("保存失败!", "警告!", MessageBoxButton.OK); } }
至此,我们完毕了动态布局的设定和保存。尝试一下吧。