曾经总认为动态布局是个非常麻烦的问题。是个非常须要功力的问题。可是貌似在.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);
} }

至此,我们完毕了动态布局的设定和保存,尝试一下吧!

WPF实现界面动态布局的更多相关文章

  1. WPF案例 (六) 动态切换UI布局

    原文:WPF案例 (六) 动态切换UI布局 这个Wpf示例对同一个界面支持以ListView或者CardView的布局方式呈现界面,使用控件ItemsControl绑定数据源,使用DataTempla ...

  2. 【源码分享】WPF漂亮界面框架实现原理分析及源码分享

    1 源码下载 2 OSGi.NET插件应用架构概述 3 漂亮界面框架原理概述 4 漂亮界面框架实现  4.1 主程序  4.2 主程序与插件的通讯   4.2.1 主程序获取插件注册的服务   4.2 ...

  3. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  4. 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff5d53bbcffd68c64411 作者:黄进——QQ音乐团队 摆脱 ...

  5. 界面动态加载时报NullPointException

    今天在做环境监测的模拟软件时,登陆页面报NullPointException 一般像我们初始化Button时,是Button btn=(Button)findViewById(R.id.button1 ...

  6. WPF中的常用布局

    一 写在开头1.1 写在开头评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好. 1.2 本文内容本文主要内容为WPF中的常用布局,大部分内容转载至https://blog.csdn.net ...

  7. android开发学习笔记系列(4)--android动态布局

    前言 在做一个有关苏果APP的项目中,但是fuck的是,我完全使用相对布局之后及线性布局之后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不做项目不知道, ...

  8. [How to] 动态布局可变高度的cell的应用

    1.简介 代码:https://github.com/xufeng79x/DynamicChangeableCell 微博界面,微信和QQ聊天界面,这些界面的布局大都不确定,且每一条消息的高度也不一样 ...

  9. 3.Dynamic Layout 动态布局。在槽中处理布局

    在应用程序中,一个界面的布局基本都是固定的. 在这个实例中,我们把管理布局的代码放在槽中.这样点击一次按钮,触发槽.布局改变一次.这样就成为一个动态布局. (一) 水平和竖直布局改变 横向: 纵向: ...

随机推荐

  1. POCO C++ lib开发环境构建

    Welcome Thank you for downloading the POCO C++ Libraries and welcome to the growing community of POC ...

  2. Noip2011提高组总结

    这套题思考的难度比较大,应该说是有四题基础题,一题比较复杂的搜索加模拟,还有一题需要深度思考一下.自己的代码漏洞还是很大,而且思考的时候会遗漏一些情况,这些错误都是致命的,去年Noip的惨败也证实了这 ...

  3. Noip2007提高组总结

    两道基础题,后两题比较麻烦,算法想出来后,还是一些细枝末节的问题,需要特别注意,感觉Noip的题目质量还是挺高的,每做一套,都感觉会有大大小小不同的收获,就要月考了,最后把07年的题目总结一下,算是这 ...

  4. jQuery.merge 源码阅读

    jQuery.merge(first,second) 概述 合并两个数组 返回的结果会修改第一个数组的内容——第一个数组的元素后面跟着第二个数组的元素. 参数 first:第一个待处理数组,会改变其中 ...

  5. 10个JavaScript小技巧

    1.变量转换 看起来很简单,但据我所看到的,使用构造函数,像Array()或者Number()来进行变量转换是常用的做法.始终使用原始数据类型(有时也称为字面量)来转换变量,这种没有任何额外的影响的做 ...

  6. android studio使用的各种问题

    1.添加权限,没有图形界面.添加权限的位置在<application>节点外,如果在节点内添加会报错的 2.查看logcat:要查看logcat的内容,要点一下设备 3.显示行号:在set ...

  7. C指针陷阱

    问题一: #include <stdio.h> int main(int argc, char *argv[]) { ]={ ,,,, }; ); printf(),*(p-)); ; } ...

  8. CSS3 总结-1

    新的边框属性 属性 描述 CSS border-image 设置所有 border-image-* 属性的简写属性. 3 border-radius 设置所有四个 border-*-radius 属性 ...

  9. YIi配置debug工具、yii配置gii工具

    $config['bootstrap'][] = 'debug';$config['modules']['debug'] = [ 'class'=>'yii\debug\Module', 'al ...

  10. Python学习之路——字符处理(一)

    一.整数: 例如:1.10.30 整数可以做以下操作: bit_length函数:返回该整数占用的最少位数: >>> x=100 >>> x.bit_length( ...