3、怎样建立一个 WPF User Control 并在一个 WPF Application 中使用它 ( VB )
与WinForm不同,WPF没有类似的子窗口。使用第三方控件感觉有失认真学习WPF的本意。初步了解后想到使用UserControl控件。UserControl依赖项属性等内容一堆,本文介绍先建立XAML文件。
在XAML命名空间折腾多时,总是“在…中无 …(类)名称”。第2篇详细研究了MSDN的文件。终其关键就2点:
1) 在用户控件中所定义的类命名,自动映射到
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation";
2) 在应用文件中规定好 xmlns:local="clr-namespace:(根命名空间)"。
此外我所走的弯路是,先新建一个UserControl项目,再新建一个应用项目(如参考文献1),然后将UserControl项目添加到应用项目。这样的做法似有不当(可能得视为2个程序集去做,未尝试)弄到大半夜也不行。
闲话少说,直接给结果。(以下使用VB2013)
3.1 怎样建立一个 WPF User Control 并使用
第一步,规划好文件名、类名。新建应用项目。用规划的应用文件名保存。我的文件名是:MyALCIDEApp。
第二步,点开“项目-->属性”面板,程序集名称自动为MyALCIDEApp。修改根命名空间为MyALCIDEApp,如下图:
第三布,编写应用程序的XAML文件,为UserControl预留位置。可先以一条语句代替:
<local:LeftBarNav></local:LeftBarNav>
此外,添加一个声明,声明类引用命名空间地址(本术语为私造):
xmlns:local="clr-namespace:MyALCIDEApp">
我的程序如下(最终代码)。此时,以上第一条语句提示错误,删除该条语句,界面窗口内运行正常。
MainWindow.XAML
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" xmlns:local="clr-namespace:MyALCIDEApp"> <!-- CSS --> <Window.Resources> <ControlTemplate x:Key="rect" TargetType="{x:Type CheckBox}"> <StackPanel> <Rectangle Name="breakRectangle" Stroke="Red" StrokeThickness="2" Width="20" Height="20"> <Rectangle.Fill> <SolidColorBrush Color="White"/> </Rectangle.Fill> </Rectangle> <ContentPresenter Margin="10" /> </StackPanel> </ControlTemplate> </Window.Resources> <!-- 停靠容器 --> <DockPanel LastChildFill="True"> <!-- 1、菜单栏 --> <Menu DockPanel.Dock="Top" VerticalAlignment="top" Height="30" FontSize="14.667" Padding="3" Background="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" > <MenuItem Header="File" Background="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}"> <MenuItem Header="New"></MenuItem> <MenuItem Header="Open"></MenuItem> <MenuItem Header="Save"></MenuItem> <Separator></Separator> <MenuItem Header="Exit"></MenuItem> </MenuItem> <MenuItem Header="Edit"> <MenuItem Header="Undo"></MenuItem> <MenuItem Header="Redo"></MenuItem> <Separator></Separator> <MenuItem Header="Cut"></MenuItem> <MenuItem Header="Copy"></MenuItem> <MenuItem Header="Paste"></MenuItem> </MenuItem> </Menu> <!-- 2、工具栏 --> <ToolBar DockPanel.Dock="Top" Height="30" VerticalAlignment="Top" Background="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"> <ComboBox SelectedIndex="0"> <ComboBoxItem>100%</ComboBoxItem> <ComboBoxItem>50%</ComboBoxItem> <ComboBoxItem>25%</ComboBoxItem> </ComboBox> <Button Content="save"></Button> <Button Content="saveall"></Button> <Separator></Separator> <CheckBox FontWeight="Bold">Bold</CheckBox> <CheckBox FontStyle="Italic">Italic</CheckBox> <CheckBox> <TextBlock TextDecorations="Underline">Underline</TextBlock> </CheckBox> <Separator></Separator> </ToolBar> <!-- 3、状态栏 --> <StatusBar Grid.Row="1" DockPanel.Dock="Bottom" Height="30" FontSize="14.667" Margin="0,0,3,3" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Background="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" SnapsToDevicePixels="True" > <!-- 定义状态栏条目容器 --> <StatusBar.ItemsPanel> <!-- 定义Grid表格 --> <ItemsPanelTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate> </StatusBar.ItemsPanel> <!-- 状态 --> <TextBlock>Left Side</TextBlock> <StatusBarItem Grid.Column="1"> <TextBlock>Right Side</TextBlock> </StatusBarItem> </StatusBar> <!-- 3、客户区 --> <DockPanel LastChildFill="True"> <!-- User Controls --> <local:LeftBarNav></local:LeftBarNav> <!-- --> <Viewbox DockPanel.Dock="Right" HorizontalAlignment="Right" Width="160"/> <Button>客户区</Button> </DockPanel> </DockPanel> </Window>
第四步,从“解决方案资源管理器”窗口,右键项目名称-->添加-->用户控件。在建立界面选择用户控件,输入规划好的文件名(我的文件名是LfetBarNav)。这样来建立用户控件。保存后,点开“项目-->属性”面板,可以看到程序集名称仍为MyALCIDEApp。根命名空间仍为MyALCIDEApp。这样用户控件与应用程序位于同一程序集。
第五步,编辑LfetBarNav.XAML。该用户控件类命名的语句其实只有一条:
x:Class="LeftBarNav"
代码如下:
LeftBarNav.XAML
<UserControl x:Class="LeftBarNav" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Border Background="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" > <StackPanel > <!-- 系统功能导航按钮************************************************* --> <Expander Margin="5" Padding="5" Header="系统功能"> <Button Padding="3">系统功能</Button> </Expander> <!-- 输入接口导航按钮************************************************* --> <Expander Margin="5" Padding="5" Header="输入接口"> <StackPanel> <Button Padding="3">A0</Button> <Button Padding="3">A1</Button> <Button Padding="3">A2</Button> </StackPanel> </Expander> <!-- 输出接口导航按钮************************************************* --> <Expander Margin="5" Padding="5" Header="输出接口"> <StackPanel> <Button Padding="3">Ec1</Button> <Button Padding="3">Ec2</Button> </StackPanel> </Expander> <!-- 逻辑控制导航按钮************************************************* --> <Expander Margin="5" Padding="5" Header="逻辑控制"> <StackPanel> <!-- 并列逻辑控制导航按钮 --> <Expander Margin="5" Padding="5" Header="并列逻辑控制"> <StackPanel> <Button Padding="3">EU31</Button> <Button Padding="3">EU32</Button> <Button Padding="3">EU33</Button> <Button Padding="3">EU34</Button> </StackPanel> </Expander> <!-- 串列逻辑控制导航按钮 --> <Expander Margin="5" Padding="5" Header="串列逻辑控制"> <StackPanel> <Button Padding="3">EU31</Button> <Button Padding="3">EU32</Button> <Button Padding="3">EU33</Button> <Button Padding="3">EU34</Button> </StackPanel> </Expander> </StackPanel> </Expander> </StackPanel> </Border> </UserControl>
第五步,选中LeftBarNav.XAML代码窗口,生成-->生成选定内容。编译成功后,点开应用程序代码窗口,错误提示消失,界面窗口运行正常。运行结果如下图。
3.2 再谈User Control类命名空间以及在应用程序中引用
讲起来命名空间篇幅蛮多。其实根本原理就两条:1、在用户控件所命名的“类名”自动映射到微软的“类命名空间”,引用时是从微软的“类命名空间”引用。2、路径都是自动的,不用考虑。只要规定好根命名空间即可。这一根命名空间在项目属性中规定,在应用程序中声明。
语句就是三条(如下),MSDN介绍的一堆俱可不予考虑。
3.2.1 在User Control中命名“类命名”的语句:
x:Class="LeftBarNav"
在名称面前不能有根目录,例如:
x:Class="MyALCIDEApp.LeftBarNav"
这是不对的。参考文献1是这样写的,实际是错误的。MyALCIDEApp是在项目属性中规定的!!!
3.2.2 在应用程序中声明的语句:
xmlns:local="clr-namespace:MyALCIDEApp"
其它都是不对的,例如按照MSDN叙述,在后边加";A..."是不行的。MyALCIDEApp是在项目属性中规定好的,用其他一概不行。
3.2.3 在应用程序中使用User Control的语句:
<local:LeftBarNav></local:LeftBarNav>
类名称LeftBarNav前后也不能加任何东西,这名称是由User Control。
参考文献
附两篇文献。第2篇下面学习依赖项参考。
1
http://www.dotnetheaven.com/article/wpf-user-controls-wpf-in-vb.net
2
http://www.codeproject.com/Articles/32825/How-to-Creating-a-WPF-User-Control-using-it-in-a-W