WPF实现界面动态布局
曾经总认为动态布局是个非常麻烦的问题。是个非常须要功力的问题。可是貌似在.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实现界面动态布局的更多相关文章
- WPF案例 (六) 动态切换UI布局
原文:WPF案例 (六) 动态切换UI布局 这个Wpf示例对同一个界面支持以ListView或者CardView的布局方式呈现界面,使用控件ItemsControl绑定数据源,使用DataTempla ...
- 【源码分享】WPF漂亮界面框架实现原理分析及源码分享
1 源码下载 2 OSGi.NET插件应用架构概述 3 漂亮界面框架原理概述 4 漂亮界面框架实现 4.1 主程序 4.2 主程序与插件的通讯 4.2.1 主程序获取插件注册的服务 4.2 ...
- WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化
WPF中的常用布局 一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...
- 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff5d53bbcffd68c64411 作者:黄进——QQ音乐团队 摆脱 ...
- 界面动态加载时报NullPointException
今天在做环境监测的模拟软件时,登陆页面报NullPointException 一般像我们初始化Button时,是Button btn=(Button)findViewById(R.id.button1 ...
- WPF中的常用布局
一 写在开头1.1 写在开头评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好. 1.2 本文内容本文主要内容为WPF中的常用布局,大部分内容转载至https://blog.csdn.net ...
- android开发学习笔记系列(4)--android动态布局
前言 在做一个有关苏果APP的项目中,但是fuck的是,我完全使用相对布局之后及线性布局之后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不做项目不知道, ...
- [How to] 动态布局可变高度的cell的应用
1.简介 代码:https://github.com/xufeng79x/DynamicChangeableCell 微博界面,微信和QQ聊天界面,这些界面的布局大都不确定,且每一条消息的高度也不一样 ...
- 3.Dynamic Layout 动态布局。在槽中处理布局
在应用程序中,一个界面的布局基本都是固定的. 在这个实例中,我们把管理布局的代码放在槽中.这样点击一次按钮,触发槽.布局改变一次.这样就成为一个动态布局. (一) 水平和竖直布局改变 横向: 纵向: ...
随机推荐
- golang语法学习(一):变量,常量以及数据类型
学习一门新的语言肯定是要从他的主要的语法開始,语法构成了整个程序设计的基础,从语法中我们也能够看到这门语言的一些特性.可是话说回来.语法这东西,不同的语言大同小异,所以这也对语法的记忆造成了一定的难度 ...
- SSIS 连接 PostgreSQL
因为工作需要,得把psql的表放到SQL Server, 找到一个PGNP(http://www.pgoledb.com/) 的适配器,不过一看要300$就没有去尝试了. 官方倒是有ODBC的驱动. ...
- spring的常用配置
bean.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http ...
- html 5 废弃的标签和属性
第一类:表现性元素 basefont big center font s strike tt u 建议用语义正确的元素代替他们,并使用CSS来确保渲染后的效果 第二类:框架类元素 因框架有很多可用性及 ...
- qnx:从API开始理解QNX -- 消息传递
从API开始理解QNX -- 消息传递 http://www.openqnx.com/chinese/viewtopic.php?f=5&t=2161 1. 频道与连接 Chann ...
- day4作业
作业内容:计算器 #!/usr/bin/env python # -*- coding:utf-8 -*- import re,time #加减字符处理函数 def handle_symbol(cal ...
- Python之路Day16
主要内容:Django基础进阶之:Django 流程.Django URL.Django Views.Django Models.Django Template.Django Admin Django ...
- Python之路:Python 基础(三)-文件操作
操作文件时,一般需要经历如下步骤: 打开文件 操作文件 一.打开文件 文件句柄 = file('文件路径', '模式') # 还有一种方法open 例1.创建文件 f = file('myfile. ...
- U-Boot在FL2440上移植(四)----支持网卡DM9000和烧写yaffs文件系统
<一>支持网卡芯片DM9000 在driver下,有网卡驱动DM9000x.c 和 DM9000x.h DM9000接在BANK4,位宽16 在include/configs/TX2440 ...
- viminfo: 无效的启动字符
当自己进入一个用户,使用vi打开一个文件时,出现以下情况: [gexd@localhost ~]$ vi test.c E575: viminfo: 无效的启动字符 位于行: int main() . ...