XAML - 命名空间
演示如何使用第三方控件库 MyControls.dll
- 首先肯定要先添加第三方库的引用或其Nuget包。
- 在CS文件或XAML文件中使用库中的类都要先导入命名空间。
CS文件中使用库中类
// 方式1
using MyNamespace.Controls.Panels;
using MyNamespace.Controls.ContentControls;
MyPanel panel = new MyPanel();
MyButton button = new MyButton();
// 方式2
var panel = new MyNamespace.Controls.Panels.MyPanel();
var button = new MyNamespace.Controls.ContentControls.MyButton();
xaml文件中使用库中类
// 导入命名空间
xmlns:euv1="clr-namespace:MyNamespace.Controls.Panels;assembly=MyControls"
xmlns:euv2="clr-namespace:MyNamespace.Controls.ContentControls;assembly=MyControls"
// 使用类
<euv1:MyPanel/>
<euv2:MyButton/>
在XAML中使用类也需要先导入命名空间。
clr-namespace:后是类所在命名空间,assembly=后是类所在程序集名称,xmlns是xml namespance缩写,后面是对命名空间的简称(如euv1和euv2),简称可以是任意简短的字符串但要求不能和其他简称重复。
演示如何在XAML中使用基础类型
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<Application.Resources>
<sys:Int32 x:Key="intMeaning">42</sys:Int32>
</Application.Resources>
显而易见,基础类型的使用也遵守 xmlns:命名空间简称="clr-namespace:命名空间;assembly=程序集名称"
。
解析XAML内置的微软命名空间
<Window x:Class="Getter在UI线程执行吗.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Getter在UI线程执行吗"
xmlns:sys="clr-namespace:Microsoft;assembly=System"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<ToggleButton Content="Click Me"/>
</StackPanel>
</Window>
xmlns:local为什么没有指定assembly |
如果在XAML文件中使用自身所在程序集的类,也需要先导入命名空间,但是可以省略assembly。缺少assembly的xmlns会在本程序集中寻找命名空间下的类。
StackPanel和ToggleButton实例化为什么不用加xmlns简称? |
上面的代码片段有4个xmlns,注意到xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
是没有简称的,而其他3个都有简称x
,local
,sys
。XAML语法允许XAML文件中最多有一个
无简称的xmlns,使用此xmlns内的控件类不需要加简称。这相当于一个语法糖,因为在一个XAML中使用最多的类就是微软内置的控件,如Button,TextBlock,ListBox,StackPanel,ToggleButton,etc.
,如果使用这些控件类时都加上简称显得比较臃肿麻烦。不加简称的类默认使用的就是缺少简称的xmlns。我们可以把微软内置的缺前缀的xmlns改成不缺简称的:
<microsoft:Window x:Class="Getter在UI线程执行吗.MainWindow"
xmlns:microsoft="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="MainWindow" Height="450" Width="800">
<microsoft:StackPanel>
<microsoft:ToggleButton Content="Click Me"/>
</microsoft:StackPanel>
</microsoft:Window>
推荐使用最频繁的xmlns不加简称,那么在逻辑树和可视化树使用其所包含的类时,不需要写简称,比较简洁!
网址作为xmlns很怪异 |
仔细观察xmlns,可以看到有些xmlns需要指定clr-namespace和assembly,但是有些xmlns只需要指定一个网址。这是为什么呢?
xmlns:sys="clr-namespace:Microsoft;assembly=System"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
如果一个控件库提供的类很多,那么命名空间大概率也会很多,使用该库,要写很多xmlns来导入众多的命名空间,这样会显得杂乱。
所以提供第三方库时,可以为部分命名空间或全部的命名空间起个统一的别名,别名可以是任意字符串,建议是项目的github网址或相关网站!那么在使用库时,只需要导入1个网址形式的命名空间即相当于导入库中多个命名空间。
为第三控件库制作网址形式命名空间的方法如下
第三方库在AssemblyInfo.cs中添加如下片段
using System.Windows.Markup;
[assembly:XmlnsDefinition("https://gihub.com/euv7/MyControls", "MyNamespace.Controls.Panels")]
[assembly: XmlnsDefinition("https://gihub.com/euv7/MyControls", "MyNamespace.Controls.ContentControls")]
[assembly: XmlnsPrefix("https://gihub.com/euv7/MyControls", "euv")]
使用第三方库的客户端
xmlns:euv="https://gihub.com/euv7/MyControls"
<euv:MyPanel/>
<euv:MyButton/>
其中
xmlns:euv="https://gihub.com/euv7/MyControls"
相当于
xmlns:euv1="MyNamespace.Controls.Panels;assembly=MyControls"
xmlns:euv2="MyNamespace.Controls.ContentControls;assembly=MyControls"
assembly: XmlnsPrefix
是推荐的xmlns简称,当然在导入网址命名空间时不使用推荐的简称也是允许的,如
不写 xmlns:euv="https://gihub.com/euv7/MyControls"
,而是写 xmlns:bruce="https://gihub.com/euv7/MyControls
"
建议第三方库提供简称,那么客户端在导入命名空间时,输入xmlns:简称=后IDE便会有智能提示。
建议网址中包含dll名称,那么客户端在输入xmlns:简称=后,不明确输入哪个网址时输入dll名称部分字符串会有智能提示。
同一个网址命名空间实际上包含多个命名空间 |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<StackPanel>
<ToggleButton Content="Click Me"/>
</StackPanel>
StackPanel的命名空间是System.Windows.Controls
ToggleButton的命名空间是System.Windows.Controls.Primitives
如果在开发第三方库时,不想让客户端使用库的时候还需要导入命名空间,那么可以直接在库的AssemblyInfo.cs文件中指定的网址xmlns就是http://schemas.microsoft.com/winfx/2006/xaml/presentation
,因为每个XAML文件都包含此微软提供的默认xmlns。但是缺点是容易导致控件类命名空间重叠冲突编译时报错说有歧义。