为了说明这个问题,假定我们需要实现一个具有特殊功能的按钮控件。编写Xaml文件如下:

<Button x:Class="TestWpf.XamlButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
Button>

对 Code Behind类,唯一的改动是把向导生成的基类从UserControl改成Button:

public partial class XamlButton : Button
{
    public XamlButton()
    {
        InitializeComponent();
    }
}

然后在主窗体中放上这个新创建的控件:

<Window x:Class="TestWpf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestWpf"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <local:XamlButton x:Name="xamlBtn" Click="xamlBtn_Click">
            <TextBlock x:Name="xamlText" Text="Xaml Button" />
        local:XamlButton>
    StackPanel>
Window>

看起来很平常的代码,但是很遗憾,编译无法通过。Visual Studio会告诉我们这样的信息:

无法在元素“TextBlock”上设置 Name 属性值“xamlText”。“TextBlock”位于元素“XamlButton”的范围之内,该元素已经具有在其他范围中定义时注册的名称。

或许是翻译的问题,这段错误提示可以说是文不对题,因为我们可以肯定的说:这个程序里面再没有别的地方用到xamlBtn或者xamlText这样的名称。

如果我们换个方式,不再用XAML声明控件,而是用C#代码定义:

public class CsButton : Button
{
}

然后再试试用同样的方式把这个控件加到主界面上:

<local:CsButton x:Name="csBtn" Click="csBtn_Click">
    <TextBlock x:Name="csText" Text="Cs Button" />
local:CsButton>

完全没有问题!csText通过代码也是可以访问的,Click处理方法可以证明这一点:

private void csBtn_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show(csText.Text);
}

如果用Silverlight来实验同样的代码,结果会稍有不同。在Silverlight XAML中添加x:Name并不会报错 ,但是运行时就会出现问题——xamlText总是等于null,并且FindName("xamlText")同样返回null,因此文本内容用自动生成的代码是无法访问的。但是以Button作为根对象来查找文本框,却能够找到:

xamlText = (TextBlock)xamlBtn.Content;
HtmlPage.Window.Alert(xamlText.Text);

此实验可以说明:用XAML来声明自定义控件是存在严重问题的,控件内容中的对象无论是通过自动生成的成员变量还是用根容器的FindName都无法访问。要绕开这个限制,有以下几种可能的途径:

1. 使用C#手工构造自定义控件,不用XAML声明;

2. 使用自定义控件的FindName找到内容对象,然后手工绑定到成员变量;

3. 使用RegisterName手工管理命名空间。此方法我没有实验,并且它仅对WPF有效,Silverlight是没有这个方法的。

上述方法2是我们最初曾经使用的方法,但是目前已经放弃了,因为手工绑定需要程序员自己编写大量无聊的代码,并且非常容易出错。方法1是目前采用的方法,为此我们删除了许多原先已经写好的XAML,全部改用C#代码手工创建,其实这个工作并不算困难,因为大多数时候XAML到C#的映射还是比较直观的,但由于Silverlight的自身设计的限制,存在一个明显的限制:

不像WPF,Silverlight里面没有简单的办法可以从代码创建一个Template。在WPF中,可以指定Template.VisualTree,但是Silverlight没有提供这个属性,所以要从代码里是生成Template是很困难的。网上曾有人提供过一个思路,即用字符串拼出模板的XAML字符串,再用XamlReader.Load读出模板对象。这个方法虽然可行,但比较丑陋,拼字符串总是下下策,维护也很困难。我们现在使用的是一个折中的办法,Template还是用XAML来保存,但是需要编写一些自定义代码,以便把C#控件和XAML中的模板关联起来。不幸的是,这个办法导致本来是同一个控件的内容不得不在两个地方分别维护,还要时时注意两边的代码保持同步,因此也不能说是一个完满的解决办法。

后记: 我现在主要的工作,是基于Silverlight开发一个应用程序平台,在此过程中已经感觉到Silverlight的一些不足,包括实现上不够完整(比如说缺少Decorator,没有OnRender),部分API在版本之间的大幅度变动(针对Silverlight 3 Beta的一些例子现在都已经失效了),也有设计上的复杂性导致的一些微妙的问题,本文所提到的就是这些问题的其中之一,给框架层面的实现带来了不少麻烦。此外值得一提的是,我们现在编译的xap包大小已经长到了800k以上,可以说和Adobe Flex编译出来的文件大小不相上下。对于文件大小“贡献”最多的是System.Windows.Controls、System.Windows.Controls.Data、System.Windows.Controls.Toolkit和System.Xml.Serialization这四个程序集,其中除了最后一个或许可以考虑以后不再用XML序列化,前面3个是不可能不使用的。所以Flex文件编译以后6、7百K的体积真的算不上大,Silverlight同样是这个水平,那些总是叫唤文件太大的同学也应该了解,RIA程序的尺寸基本上也就这样了,除了用RSL之类技术切割一下以外,已经没有多大优化的余地了。如果这个大小您也不能接受的话,那还是用回Ajax吧。

艾伟_转载:WPF/Silverlight陷阱:XAML自定义控件的嵌套内容无法通过名称访问相关推荐

  1. 艾伟_转载:简单的自动更新程序实现

    本文将演示一种桌面程序自动更新方案,其步骤比较多,但原理非常简单,通用性尚可,对于小型应用来说,直接拿去就可以用了. 原理 服务器端的结构是这样的: 其工作原理如下: Update.asmx仅提供一个 ...

  2. 艾伟_转载:探索.Net中的委托

    废话 我本来以为委托很简单,本来只想简简单单的说说委托背后的东西,委托的使用方法.原本只想解释一下那句:委托是面向对象的.类型安全的函数指针.可没想到最后惹出一堆的事情来,越惹越多,罪过,罪过.本文后 ...

  3. 艾伟_转载:学习 ASP.NET MVC (第五回)理论篇

    本系列文章导航 学习 ASP.NET MVC (第一回)理论篇 学习 ASP.NET MVC (第二回)实战篇 学习 ASP.NET MVC (第三回)实战篇 学习 ASP.NET MVC (第四回) ...

  4. 艾伟_转载:C#语言基础常见问题汇总

    概述 1.什么是C#? C#是Microsoft公司设计的一种编程语言.它松散地基于C/C++,并且有很多方面和Java类似. Microsoft是这样描述C#的:"C#是从C和C++派生来 ...

  5. 艾伟_转载:.NET 4.0中数组的新增功能

    1.两数组是否"相等"? 在实际开发中,有时我们需要比对两个数组是否拥有一致的元素,例如,以下两个数组由于拥有相同的元素,因此被认为是相等的: int[] arr1 = new i ...

  6. 艾伟_转载:从ASP.NET的PHP执行速度比较谈起

    上星期我在InfoQ发表了一篇新闻,对Joe Stagner在博客上发表的三篇关于ASP.NET与PHP性能对比的文章进行了总结.写新闻其实挺不爽的,因为不能夹杂个人的看法,只能平铺直叙陈述事实.当然 ...

  7. 艾伟_转载:把事件当作对象进行传递

    最近在琢磨一些事情,和API设计有关.API设计在很多时候是和语言特性有关的,因此如Java这样的语言,在API设计时会处处受到压抑.而C#就能够出现如Moq或Fluent NHIbernate这样的 ...

  8. 艾伟_转载:.NET设计模式:观察者模式(Observer Pattern)

    概述 在软件构建过程中,我们需要为某些对象建立一种"通知依赖关系" --一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知.如果这样的依赖关系过于紧密,将 ...

  9. 艾伟_转载:.NET内存管理、垃圾回收

    1. Stack和Heap 每个线程对应一个stack,线程创建的时候CLR为其创建这个stack,stack主要作用是记录函数的执行情况.值类型变量(函数的参数.局部变量 等非成员变量)都分配在st ...

最新文章

  1. 【Android 安装包优化】使用 lib7zr.a 静态库处理压缩文件 ( 交叉编译 lib7zr.a 静态库 | 安卓工程导入静态库 | 配置 CMakeLists.txt 构建脚本 )
  2. IAR在线调试时用DEBUG打印调试信息
  3. ACM卡常处理办法(虽然我到现在没遇到)
  4. 位向量(bit vector)(算法导论第十一章11.1-2)
  5. AutoMapper的使用
  6. 又重新让aspspider.net支持中文PDF输出了
  7. java仿qq gui_Java仿QQ登入页面
  8. 在SPA应用中利用JWT进行身份验证
  9. PHP邮件扩展,PHP邮件扩展:mailpp
  10. java arraydeque poll,Java ArrayDeque pollLast()方法
  11. 鲁大师原来真的姓鲁呀
  12. 华为 hg8120c 超级密码获取过程
  13. 【个人笔记】Ubuntu18.04 安装显卡驱动
  14. 用 UrlSchemes 实现调用应用并传参
  15. 安装K3s 和 ingress-nginx
  16. LP Wizard10.5破解笔记
  17. 排列组合问题的通用算法
  18. 【基础知识】~ 竞争/冒险
  19. 云栖科技评论第62期:想象力比雄心更重要
  20. 国家信息安全测评信息安全服务资质证书(安全工程类一级)申请条件

热门文章

  1. 学爬虫,需要掌握哪些Python基础?
  2. 普通交换机不需要任何设置,也不能设置
  3. 在Windows Server 2012中配置NAT代理服务器
  4. 调整xfce中的鼠标大小到48以上-目前还没有完成
  5. flink-jdbc-driver和flink-sql-gateway的作用
  6. wine应用运行后字体都是问号
  7. linux下面把png文件转化为背景透明
  8. ubuntu18.10 cosmic更换阿里云的源
  9. SMO算法原理转载+自己补充
  10. NLTK自带的词干提取器