原文:用MVVM模式开发中遇到的零散问题总结(5)——将动态加载的可视元素保存为图片的控件,Binding刷新的时机


  在项目开发中经常会遇到这样一种情况,就是需要将用户填写的信息排版到一张表单中,供打印或存档。这里就以保存为图片为例,比如我需要实现下面的功能:

将图片   根据用户信息保存为

总体思路


  1.建个UserControl将背景设置为表单图片。

  2.在姓名的位置添加Textblock控件,将Text绑定到Name属性上。

  3.动态加载UserControl,再将整个UserControl可视树转化为一张图片,保存。

实现过程


  关于怎么设置背景,和布局Textblock我就不多说了,相信大家都会。要注意的是,因为之后我要用XamlReader.Load()来动态加载XAML所以UserControl要把X:Class="xxx"这段给删了。

  接下来直接看代码,基本每句都写了注释

需要生成图片的XAML:

<Grid >
<Image Source="pack://siteoforigin:,,,/view/Print/Images/XXX.jpg" />
<TextBlock Height="88" HorizontalAlignment="Left" Margin="928,1624,0,0" Text="{Binding Name}" VerticalAlignment="Top" Width="240" FontSize="64" />
</Grid>

控件代码:

/// <summary>
/// 设置需要生成的Xaml的地址
/// </summary>
public string XamlUrl
{
get { return (string)GetValue(XamlUrlProperty); }
set { SetValue(XamlUrlProperty, value); }
}
public static readonly DependencyProperty XamlUrlProperty =
DependencyProperty.Register("XamlUrl", typeof(string), typeof(CopXaml2Bmp), null); /// <summary>
/// 生成的图片地址
/// </summary>
public string BmpUrl
{
get { return (string)GetValue(BmpUrlProperty); }
set { SetValue(BmpUrlProperty, value); }
}
public static readonly DependencyProperty BmpUrlProperty =
DependencyProperty.Register("BmpUrl", typeof(string), typeof(CopXaml2Bmp),null); /// <summary>
/// 设置dpi
/// </summary>
public int Dpi
{
get { return (int)GetValue(DpiProperty); }
set { SetValue(DpiProperty, value); }
}
public static readonly DependencyProperty DpiProperty =
DependencyProperty.Register("Dpi", typeof(int), typeof(CopXaml2Bmp), null); private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
try
{
FileStream fs = new FileStream(XamlUrl, FileMode.Open, FileAccess.Read);//动态加载XAML
ContentControl myGrid = XamlReader.Load(fs) as ContentControl;
//myGrid.DataContext = this.DataContext;//设置datacontext
double width = (this.Parent as Grid).Width;//获取母容器的高宽
double height = (this.Parent as Grid).Height; myGrid.Loaded += new RoutedEventHandler((sender1, e1) =>
{
(this.Parent as Grid).Children.Remove(myGrid);//从母容器中移除该内容 var size = new Size(myGrid.Width, myGrid.Height);
myGrid.Measure(size);//二次布局,因为只是在内存中没有显示在UI上,需要经过布局才有内容
myGrid.Arrange(new Rect(new Point(, ), size)); System.IO.FileStream fs1 = new System.IO.FileStream(BmpUrl, System.IO.FileMode.Create);//创建一个文件流来存图片
RenderTargetBitmap bmp = new RenderTargetBitmap((int)myGrid.Width, (int)myGrid.Height, Dpi, Dpi, PixelFormats.Default);//visual对象转位图
bmp.Render(myGrid);//呈现visual
BitmapEncoder encoder = new TiffBitmapEncoder();//编码为图像流
encoder.Frames.Add(BitmapFrame.Create(bmp));//添加帧
encoder.Save(fs1);//保存文件
fs1.Close(); (this.Parent as Grid).Width = width;//大小还原
(this.Parent as Grid).Height = height;
});
(this.Parent as Grid).Width = myGrid.Width;//将母容器的高宽设置为需要的大小
(this.Parent as Grid).Height = myGrid.Height;
(this.Parent as Grid).Children.Add(myGrid);//添加进母容器让其暂时显示,以显示绑定的信息 }
catch
{ }
}

使用控件代码(其父容器的datacontext中含有Name属性):

<Assistant:Xaml2Bmp XamlUrl="view/Print/XXX.xaml" BmpUrl="d:/test.bmp" Dpi="96" HorizontalAlignment="Right" Height="100" Margin="0,0,204,44" VerticalAlignment="Bottom" Width="100"/>

这样就将动态加载的XAML生成了d:/test.bmp图片。

  说实话,实现这个功能没什么难的,写这篇博客的目的在于,做这个控件时让我了解到了一个Binding刷新的问题。

  通过XamlReader.Load()加载的XAML对其设置datacontext,对应的Textblock.Text的内容为"",而不是绑定的内容。而当元素在UI上显示时,才会刷新数据绑定,从而让Textblock.Text的内容为绑定到的datacontext对应的节点上。

  所以上面的代码中,我把动态加载的XAML添加进了控件的父容器中,让其刷新绑定,并在其加载完成后从父容器中移除该控件,对于用户来说是什么都看不到的,然后将其转换为图片。父容器的大小也要能够容纳整个控件才行,生成的图片显示的只有父容器的范围部分。

更新:实践证明如果需要生成的元素里面包含自定义style的时候,需要在元素还在界面上显示时进行打印,一旦从UI上Remove了该元素后貌似就会把自定义style释放掉,生成的图片有关自定义控件的地方就为空白,也就是说WPF程序当元素在UI上显示时才会加载样式,一旦从UI上移除就卸载掉,以提高性能。所以上面的代码需要把(this.Parent as Grid).Children.Remove(myGrid);这句移到生成图片那一句的后面。

  

用MVVM模式开发中遇到的零散问题总结(5)——将动态加载的可视元素保存为图片的控件,Binding刷新的时机的更多相关文章

  1. 用MVVM模式开发中遇到的零散问题总结(4)——自制摄像头拍摄大头贴控件

    原文:用MVVM模式开发中遇到的零散问题总结(4)--自制摄像头拍摄大头贴控件 一直有个疑问,为什么silverlight对摄像头支持这么好,WPF却一个库都没有....于是我各种苦恼啊,各种Code ...

  2. 用MVVM模式开发中遇到的零散问题总结(2)

    原文:用MVVM模式开发中遇到的零散问题总结(2) 本节目录: 1.解决动画属性被劫持问题 2.设置页面焦点默认所在对象 3.XAML模拟键盘按键 4.DataGrid数据源绑定到复杂格式(dynam ...

  3. 用MVVM模式开发中遇到的零散问题总结(3)——自制正则表达式万能绑定转换器

    原文:用MVVM模式开发中遇到的零散问题总结(3)--自制正则表达式万能绑定转换器 前言 最近接受了3个项目的洗礼,出差近3个月,各种北京.广州.昆明来回奔波,好久没写博客了,之前我觉得我遇到的问题都 ...

  4. 用MVVM模式开发中遇到的零散问题总结(1)

    https://www.cnblogs.com/tong-tong/archive/2011/11/28/2250948.html

  5. 会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

    在上篇<会员管理系统的设计和开发(1)>介绍了关于会员系统的一些总体设计思路和要点,经过一段时间开发,软件终于完成并发布.在这期间,碰到了不少技术难点,并积累了不少开发心得和经验,本篇继续 ...

  6. 【WPF开发备忘】使用MVVM模式开发中列表控件内的按钮事件无法触发解决方法

    实际使用MVVM进行WPF开发的时候,可能会用到列表控件中每行一个编辑或删除按钮,这时直接去绑定,发现无法响应: <DataGridTemplateColumn Header="操作& ...

  7. Winform开发框架之客户关系管理系统(CRM)的开发总结系列4-Tab控件页面的动态加载

    在前面介绍的几篇关于CRM系统的开发随笔中,里面都整合了多个页面的功能,包括多文档界面,以及客户相关信息的页面展示,这个模块就是利用DevExpress控件的XtraTabPage控件的动态加载实现的 ...

  8. C#中动态加载和卸载DLL

    在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载.在C#中我们也能使用Assembly.LoadFile实 ...

  9. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)1----C#中动态加载和卸载DLL

    我们知道在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载. 在C#中我们也能使用Assembly.Load ...

随机推荐

  1. [Docker] Prune Old Unused Docker Containers and Images

    In this lesson, we will look at docker container prune to remove old docker containers. We can also ...

  2. Mac OSX 下配置 LNMP开发环境

    不久前负责了一个项目需要配置PHP7的开发环境,因为之前所有的项目用的是PHP5的,所以研究了这些东西,但是很遗憾,电脑出了问题,不得已重装了系统,然后你懂得...什么都没有了,要重新来过.. 虽然本 ...

  3. Springmvc+Shiro实战

    原文链接:http://blog.csdn.net/qq_37936542/article/details/79010449 springmvc+shiro实现系统粗细粒度的权限管理步骤: 1:表格设 ...

  4. Surf算法特征点检测与匹配

    Speeded Up Robust Features(SURF,加速稳健特征),是一种稳健的局部特征点检测和描述算法.最初由Herbert Bay发表在2006年的欧洲计算机视觉国际会议(Europe ...

  5. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(3)输入输出函数

    一.基本的输入和输出函数的用法 1.printf()  //屏幕输出 用法: (1)printf("字符串\n"); (2)printf("输出控制符", 输出 ...

  6. Oracle成长点点滴滴(2)— 权限管理

    权限管理中权限包含系统权限以及对象权限.在解说权限管理之前我们先来了解用户的创建以及授权这些前提. 1.      创建用户以及授权 Ø  默认用户 既然提到了创建用户,首先必须先把用户的知识攻克了. ...

  7. 【BZOJ 1005】[HNOI2008]明明的烦恼(化简的另一种方法)

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1005 [题意] [题解] 题目和题解在上一篇; 这里 对 [(m^(n-2-tot)) ...

  8. 【Dijkstra+邻接表求次短路】POJ Sightseeing 3463

    Language: Default Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7766   Ac ...

  9. 欢迎阅读 Erlang OTP 设计原理文档

    http://erldoc.com/doc/otp-design-principles/index.html 原文: OTP Design Principles 翻译: ShiningRay 有任何问 ...

  10. boost::any在降低模块之间耦合性的应用

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在开发大型系统中,遵循这样一个原则:模块之间低耦合,模块内高内聚.比如系统中模块有界面模块和算法模块两种,一般是界面模 ...