【Silverlight】解决DataTemplate绑定附加属性

    本文 Silverlight 版本:4.0。

    首先定义数据类型,此文始终使用此定义类型。

    public class SimpleData : ViewModelBase{private string _text;private int _column, _row;public string Text { get { return _text; } set { _text = value; OnPropertyChanged("Text"); } }public int Column { get { return _column; } set { _column = value; OnPropertyChanged("Column"); } }public int Row { get { return _row; } set { _row = value; OnPropertyChanged("Row"); } }}

    前台代码:

    <Grid x:Name="LayoutRoot" Background="White"><ItemsControl ItemsSource="{Binding}"><ItemsControl.ItemTemplate><DataTemplate><TextBox Text="{Binding Text}"Foreground="Green"Grid.Row="{Binding Row}"Grid.Column="{Binding Column}"Height="30" Width="150"/></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><Grid ShowGridLines="True"><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions></Grid></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl></Grid>

    后台代码:

    public partial class MainPage : UserControl{public MainPage(){InitializeComponent();this.DataContext = new SimpleData[]{new SimpleData{ Text = "111111", Column = 0, Row = 0 },new SimpleData{ Text = "222222", Column = 1, Row = 1 }, new SimpleData{ Text = "333333", Column = 0, Row = 2 }, };}}

    可以看出这段代码的本意是通过绑定的方式设置,在 ItemsControl 里面显示 3 个 TextBox,同时指定了相应在 Grid 的行和列。

    但是,你懂的!

    这样的代码肯定是不能正确运行。特别是在Silverlight。

    如果这是在 WPF 环境,很庆幸你还可以用 ItemContainerStyle 搞定:

            <ItemsControl.ItemContainerStyle><Style><Setter Property="Grid.Row" Value="{Binding Row, Mode=OneWay}"/><Setter Property="Grid.Column" Value="{Binding Column, Mode=OneWay}"/></Style></ItemsControl.ItemContainerStyle>

    只可惜这是在 Silverlight 环境。我们只能够想别的办法了。

 

    为什么不可以?拿出 Silverlight Spy 或者 Snoop 查看相应的 VisualTree。可以看到在 TextBox 外面还套了一个 ContextPresenter。

201109112135557404.png

    于是我们可以想到,能不能设置 ContextPresenter 的 Grid.Row 和 Grid.Colume 达到控制行列的目的?

    于是我们得到下面的思路,使用附加属性把相应的绑定关系提升。

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;namespace Delay
{public class UpUp : DependencyObject{// Using a DependencyProperty as the backing store for Up.  This enables animation, styling, binding, etc...public static readonly DependencyProperty UpProperty =DependencyProperty.RegisterAttached("Up", typeof(string), typeof(UpUp), new PropertyMetadata(string.Empty));public static void SetUp(FrameworkElement element, string value){HanderClosure hander = element.GetValue(UpProperty) as HanderClosure;if (hander == null){hander = new HanderClosure(element, value);element.SetValue(UpProperty, value);element.LayoutUpdated += new EventHandler(hander.element_LayoutUpdated);}}public static string GetUp(FrameworkElement element){HanderClosure hander = element.GetValue(UpProperty) as HanderClosure;if (hander == null)return null;elsereturn hander.OrgParamenter;}private class HanderClosure{private FrameworkElement _elem = null;private string[] propertys = null;private int _level;private UpMode _mode;private string _orgParamenter;public string OrgParamenter { get { return _orgParamenter; } }public HanderClosure(FrameworkElement element, string parameter){if (element == null)throw new ArgumentNullException("element");if (parameter == null)throw new ArgumentNullException("parameter");_elem = element;_level = 1;_mode = UpMode.Copy;_orgParamenter = parameter;string[] array = parameter.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);if (array.Length == 0)throw new ArgumentException("parameter");propertys = array[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);if (array.Length > 1){int num;if (int.TryParse(array[1].Trim(), out num)){_level = num;}}if (array.Length > 2){UpMode mode;if (Enum.TryParse<UpMode>(array[2].Trim(), true, out mode)){_mode = mode;}}}public void element_LayoutUpdated(object sender, EventArgs e){FrameworkElement parent = _elem;for (int i = 0; i < _level && parent != null; i++){parent = VisualTreeHelper.GetParent(parent) as FrameworkElement;}if (parent == null)return;foreach (string property in propertys){Apply(_elem, parent, property.Trim());}}// Copyright (C) Microsoft Corporation. All Rights Reserved.// This code released under the terms of the Microsoft Public License// (Ms-PL, http://opensource.org/licenses/ms-pl.html).private void Apply(FrameworkElement element1, FrameworkElement element2, string property){var array = property.Split('.');if (array.Length != 2)throw new ArgumentException("property");string typeName = array[0].Trim();string propertyName = array[1].Trim();Type type = null;foreach (var assembly in AssembliesToSearch){// Match on short or full nametype = assembly.GetTypes().Where(t => (t.FullName == typeName) || (t.Name == typeName)).FirstOrDefault();if (type != null)break;}if (null == type){// Unable to find the requested type anywherethrow new ArgumentException(string.Format(CultureInfo.CurrentCulture,"Unable to access type \"{0}\". Try using an assembly qualified type name.",typeName));}// Get the DependencyProperty for which to set the BindingDependencyProperty dp = null;var field = type.GetField(propertyName + "Property",BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);if (null != field){dp = field.GetValue(null) as DependencyProperty;}if (null == dp){// Unable to find the requsted propertythrow new ArgumentException(string.Format(CultureInfo.CurrentCulture,"Unable to access DependencyProperty \"{0}\" on type \"{1}\".",propertyName,type.Name));}BindingExpression binding = element1.GetBindingExpression(dp);object value = element1.GetValue(dp);if (binding != null){element2.SetBinding(dp, binding.ParentBinding);}else if (value != null){element2.SetValue(dp, value);}if (_mode == UpMode.Move)element1.ClearValue(dp);}// Copyright (C) Microsoft Corporation. All Rights Reserved.// This code released under the terms of the Microsoft Public License// (Ms-PL, http://opensource.org/licenses/ms-pl.html)./// <summary>/// Gets a sequence of assemblies to search for the provided type name./// </summary>private IEnumerable<Assembly> AssembliesToSearch{get{// Start with the System.Windows assembly (home of all core controls)yield return typeof(Control).Assembly;#if SILVERLIGHT && !WINDOWS_PHONE// Fall back by trying each of the assemblies in the Deployment's Parts listforeach (var part in Deployment.Current.Parts){var streamResourceInfo = Application.GetResourceStream(new Uri(part.Source, UriKind.Relative));using (var stream = streamResourceInfo.Stream){yield return part.Load(stream);}}
#endif}}}private enum UpMode{Move,Copy,}}
}

    如何使用?使用非常简单!

    在你的项目中增加 UpUp 之后,在需要提升绑定级别的 Page 的 Xaml 中引入命名空间 xmlns:delay="clr-namespace:Delay"。然后在需要提升绑定级别的控件中加入属性 delay:UpUp.Up="Grid.Row,Grid.Column"。得到完整的前台代码如下:

<UserControl x:Class="TestValueBindingInItemTemplate.MainPage"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"xmlns:delay="clr-namespace:Delay"mc:Ignorable="d"d:DesignHeight="300" d:DesignWidth="400"><Grid x:Name="LayoutRoot" Background="White"><ItemsControl ItemsSource="{Binding}"><ItemsControl.ItemTemplate><DataTemplate><TextBox Text="{Binding Text}"Foreground="Green"Grid.Row="{Binding Row}"Grid.Column="{Binding Column}"Height="30" Width="150"delay:UpUp.Up="Grid.Row,Grid.Column"/></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><Grid ShowGridLines="True"><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions></Grid></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl></Grid>
</UserControl>

    UpUp.Up 应该如何填写?实际上 UpUp.Up 属性有具体的语法格式:

 

UpUp.Up="Type.Property[,Type.Property ...][;Level[;Move|Copy]]"

 

    其中

    Type.Property 是需要提升绑定关系的属性名称,可以用逗号把多个属性名称隔开。

    Level 是整数,表示需要提升的层次。在 VisualTree 中向上一层为一个层次。

    Move|Copy 是枚举类型,表示提升之后保留原来的绑定关系。

    例如:delay:UpUp.Up="Grid.Row,Grid.Column;1;Copy"

 

    有了 UpUp 之后,对于类似的绑定问题可以轻而易举的完成了!

 

PS:WPF 也可以用此方法实现,但是有细节方面的差异。

1、不能够使用SetXXX GetXXX,要使用 XXX 属性。

2、需要注册 PropertyChangedCallback 事件,并将相关注册 Hander 部分放置到此方法内。

 

本文完整代码在此下载:http://files.cnblogs.com/Aimeast/SLTestValueBindingInItemTemplate.zip

转载于:https://www.cnblogs.com/Aimeast/archive/2011/09/11/2173788.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261243.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

青春无悔

青春像是一座城&#xff0c;放纵的思想、禁锢的世界总让自己感到如履薄冰&#xff0c;只能踽踽独行在阡陌的途中&#xff0c;我喜欢世界是自由的&#xff0c;我喜欢生活是淡然的&#xff0c;淡然的境界早已挣脱时空的枷锁&#xff0c;穿行在历朝历代&#xff0c;如莲花般盛开在…

java中udi_Java读取.properties配置文件的方法

java中的properties文件是一种配置文件&#xff0c;主要用于表达配置信息&#xff0c;文件类型为*.properties&#xff0c;格式为文本文件&#xff0c;文件的内容是格式是 "键值"的格式&#xff0c;在properties文件中&#xff0c;可以用"#"来作注释&#…

android 中文 api (72) —— BluetoothSocket[蓝牙]

前言 本章内容是 android.bluetooth.BluetoothSocket&#xff0c;为Android蓝牙部分的章节翻译。蓝牙通讯套接字&#xff0c;代表了与远端设备的连接点&#xff0c;使用socket本地程序可以通过inputstream和outputstream与远端程序进行通讯。版本为 Android 2.3 r1&#xff0c;…

Linux常用命令(二)

19. 文件压缩命令 &#xff08;1&#xff09;。gzip [文件名]  压缩后的文件格式是.gz   只能压缩文件不能压缩目录 不保留源文件 &#xff08;2&#xff09;。gunzip [文件名]  解压缩命令 &#xff08;3&#xff09;。tar 选项[cvf] [目录]  打包目录  压缩后的文件…

五行代码终极完美解决从IE6到Chrome所有浏览器的position:fixed;以及闪动问题

这个方法其实已经使用很久了&#xff0c;之前主要在嵌入式WebQQ等产品中用过&#xff0c;现在拿出来分享一下吧&#xff0c;是目前最简洁的方式来实现ie6的position:fixed; 失效bug&#xff0c;以及的其他方法的闪动问题&#xff0c;CSS代码如下&#xff0c;很简单&#xff0c;…

致年轻开发人员的一封信

我收到了很多年轻开发人员写给我的邮件&#xff0c;希望可以提升自己的编程能力。我肯定不是第一个讨论这个话题的人&#xff0c;所以我不确定还可以说出什么新意。然而&#xff0c;这里我认为还是非常值得列出我认为很重要的几点吧。 要跟其他开发者一起工作。我们正处在科技史…

笔记整理之 SHELL 变量

变量的类型&#xff1a;1.自定义变量定义变量&#xff1a; 变量名变量值 变量名必须以字母或下划线开头&#xff0c;区分大小写 url1test.3glong.com 引用变量&#xff1a; $变量名 或 ${变量名} 查看变量&#xff1a; echo $变量名 set(所有变量&#xff1a;包括自定…

Node的异步与java的异步_node.js和异步编程回文

以下代码不是异步的&#xff0c;为什么以及如何制作呢&#xff1f;function compute(callback){for(var i 0; i < 1000 ; i){}callback(i);}我将假设你的代码试图说&#xff0c;“我需要做1000次&#xff0c;然后在一切都完成时使用我的回调” .即使你的for循环也不会在这里…

N个三角形分割平面个数(数学)

一个三角形的时候&#xff0c;再加一个三角形&#xff0c;每一条变会与第一个三角形的两条边相交&#xff0c;这样增加2个小三角形&#xff0c;即两个面。f(2)3*2f(1)&#xff0c;再加一个三角形&#xff0c;每一条边会与前两个三角形的四条边相交&#xff0c;形成四个小三角形…

2011年9月19日 面试重点:asp.net运行原理和生命周期

面试重点&#xff1a;asp.net运行原理和生命周期1、ispostback回调机制isPostBackfalse !IsPostBackture 当前页面是第一次加载IsPostBack 由于用户交互(page.submit())提交页面而产生的加载,二次加载html客户端代码将ispostback值存放在viewstate隐藏字段中<input type&quo…

redis——集群

2019独角兽企业重金招聘Python工程师标准>>> 现实中redis需要若干台redis服务器的支持&#xff1a; &#xff08;1&#xff09;从结构上&#xff0c;单个Redis服务器会产生单点故障&#xff0c;同时一台服务器需要承受所有的请求负载。这就需要为数据生成多个副本并…

queue java 用法_Java队列(Queue)用法

Java 实例 - 队列(Queue)用法队列是一种特殊的线性表&#xff0c;它只允许在表的前端进行删除操作&#xff0c;而在表的后端进行插入操作。LinkedList类实现了Queue接口&#xff0c;因此我们可以把LinkedList当成Queue来用。以下实例演示了队列(Queue)的用法&#xff1a;Main.j…

POJ 2409 Let it Bead (Polya定理)

题意 用k种颜色对n个珠子构成的环上色&#xff0c;旋转翻转后相同的只算一种&#xff0c;求不等价的着色方案数。 思路 Polya定理 X是对象集合{1, 2, ……, n}&#xff0c; 设G是X上的置换群&#xff0c;用M种颜色染N种对象&#xff0c;则不同的染色方案数为&#xff1a; λ(g)…

seo

SEO&#xff08;Search Engine Optimization&#xff09;&#xff0c;汉译为搜索引擎优化&#xff0c;是较为流行的网络营销方式&#xff0c;主要目的是增加特定关键字的曝光率以增加网站的能见度&#xff0c;进而增加销售的机会。分为站外SEO和站内SEO两种。SEO的主要工作是通…

Ubuntu Server 之Apache2 虚拟主机配置指南(个人实践解读)

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/468531 这是完成在ubuntu Server的apache服务器上安装一个虚拟主机的具体配置。希望对用到的朋友有所帮…

java10支持mybatis_写了10年的代码,我最怕写Mybatis这些配置,现在有详解了

作者 | 阿进的写字台链接 | www.cnblogs.com/homejim/p/9782403.html在使用 mybatis 过程中&#xff0c; 当手写 JavaBean和XML 写的越来越多的时候&#xff0c; 就越来越同意出错。这种重复性的工作&#xff0c; 我们当然不希望做那么多。还好&#xff0c; mybatis 为我们提供…

webservice-WebService试题

ylbtech-doc:webservice-WebService试题WebService试题 1.A,返回顶部001&#xff0e;{WebService题目}下列是Web服务体系结构中的角色的是&#xff08;&#xff09;&#xff08;选择3项&#xff09; A&#xff09;服务提供者 B&#xff09;服务请求者 C&#…

Session的模拟

Session相关的mock Session相关的mock主要有以下两个步骤&#xff1a; 1&#xff09; HttpContext对象的实例化 session属于HttpContext对象&#xff0c;所以简单来说&#xff0c;就是我们需要构造一个HttpContext&#xff0c;对象然后在给其中的Session附值。然后再把它指定到…

定时自动启动任务crontab命令用法

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://navyaijm.blog.51cto.com/4647068/816636 crontab简介 crontab命令常见于Unix和类Unix的操作系统之中&#xff0c;用于设置周期性被执行的…

9读书1-我在义务发财(1)

母亲说完&#xff0c;父亲就起身出门了。我没出门&#xff0c;上楼到了我的房间里。我要干两件事情&#xff1a;一是写“发财”两个大字贴在我的床头&#xff1b;二是在手上刺青。 //有时候为了达到自己心中说想打目标&#xff0c;必须时时刻刻的提醒自己&#xff0c;这就是一些…