<h1>ListView示例(一) - <span class="color_h1">(十八)</span></h1><p><br/></p><p>经过前面的学习,今天我做一个比较综合的WPF程序示例,主要包括以下功能: </p><p>1) 查询功能。从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,然后展示到WPF的Window上的一个ListView上。</p><p>2) 数据联动功能。当鼠标左键选中ListView中的某一条记录时,在ListView框下面文本框中显示详细信息。</p><p>3) 修改功能。修改TextBox中的内容后,点击“更新”按钮,把修改后的数据保存到数据库中,同时与Listview联动。</p><p><br/></p><h1 style="font-size: 16px;font-weight:bold">第一步、建立一个WPF项目</h1><p> 可参考第一章内容《新建WPF工程》:<a target="_blank" href="/Course?Id=13§ion=2">/Course?Id=13§ion=2</a></p><p><br/></p><h1 style="font-size: 16px;font-weight:bold">第二步:安装EntityFramework</h1><p> 使用NuGet下载最新版的EntityFramework。在解决方案资源管理器中——>在项目WpfApp鼠标右键单击——>弹出一个菜单,选中“管理解决方案的NuGet程序包”,打开NuGet程序包管理界面。安装完如下:</p><p><img class="pimg" src="/upload/image/微信截图_20211203112819.jpg"/></p><p><br/></p><h1 style="font-size: 16px;font-weight:bold">第三步、WPF界面布局</h1><p> 1)在新建完WPF项目之后,WPF项目中有一个默认界面,将鼠标放在方框的边缘点击就会产生相应的分割线,我们先将窗体随意的分成三行,以后在XAML代码中再进行具体的调整。在添加完分割线之后,看一下下方的XAML代码区域,每个分割线都做为一行RowDefinition。如下图。</p><p><img class="pimg" src="/upload/image/微信截图_20211203132429.gif"/></p><p><br/></p><p> 2)在XAML代码编辑界面中将我们刚才定义的三行,修改其高度,代码如下。 </p><pre style="overflow-x:auto;font-size: 15px;" class="brush:xml;toolbar:false;"><Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions></pre><p><br/></p><table class="w_table" style="table-layout:fixed;" width="70%" border="1"><thead><tr style="height:35px" align="center" class="firstRow"><th style="width: 15%; border-width: 2px 1px 1px; border-style: solid; border-color: windowtext;">行</th><th style="border-width: 2px 1px 1px; border-style: solid; border-color: windowtext;">说明</th></tr></thead><tbody><tr style="height:35px"><td style="white-space: normal; border-width: 1px; border-style: solid;">第1行</td><td style="white-space: normal; border-width: 1px; border-style: solid;">设为*用来放置ListView,这样在程序的实际运行过程会尽可能的充满整个区域</td></tr><tr style="height:35px"><td style="white-space: normal; border-width: 1px; border-style: solid;">第2行</td><td style="white-space: normal; border-width: 1px; border-style: solid;">设为Auto尽量紧凑排列,减少空间的占用(如果这一行中没有放任何控件的话,他会小到0,这样在界面上就不会显示。)</td></tr><tr style="height:35px"><td style="white-space: normal; border-width: 1px; border-style: solid;">第3行</td><td style="white-space: normal; border-width: 1px; border-style: solid;">设为22固定值,只是用来放置按钮控件</td></tr></tbody></table><p><br/></p><p><img class="pimg" src="/upload/image/微信截图_20211203133012.gif"/></p><p><br/></p><p>说明:</p><p> 如果是你经常做ASP.NET或是windows的开发,可能会形成一个习惯——直接从工具箱上把控件拖拽到需要的地方。 这样直接拖放控件的方式,VS会自动生成一个固定的坐标,但是这种方式在WPF中不推荐使用,在WPF中推荐使用 Canvas、StackPanel、WrapPanel、DockPanel和Grid面板组合使用来组装界面。 </p><p><br/></p><p> 对于WPF的界面布局,有以下几点建议:</p><p> 第一、控件的布局应该有容器来决定,而不是通过控件的margin属性来控制位置。 </p><p> 第二、控件应避免明确的定义具体的尺寸,因为显示器分辨率及windows窗体的大小都有可能随时改变,如果明确的定义尺寸。 </p><p>当窗体变动后就会出现大面积的空白或是缺失。但为了控件功能及效果的展示,应该限定一个可接受的最大及最小尺寸。 </p><p>通过MinWidth, MinHeight, MaxWidth, MaxHeight属性可以实现这一点。</p><p> 第三、由于现在显示器分辨率非常多(1366×768、1600×900、、1980×1080等等),如果将界面元素位置设置成与屏幕坐标相关,这样做的话是会有风险的。 </p><p> 第四、容器应将有效空间共享给其子控件,这也是为了不在窗体调整后,遗留出大块的空余。 </p><p> 第五、容器嵌套使用,因为不同的容器,表现效果不同,必要时应结合使用。</p><p><br/></p><p> 3)接下来在工具箱中双击ListView,一个小框会出现在界面上。 </p><p> 4)接下来在工具箱中双击WrapPanel,又一个大框会出现在界面上。</p><p> 5)再增加一个Button按钮。</p><p><img class="pimg" src="/upload/image/微信截图_20211203135206.gif"/></p><p><br/></p><p> 6) 在拖放完了上面这些控件后,你会发觉当前界面有点乱了,这时刚才我们在顶层Grid上面的画的分割线就要起到作用了,让我们在XAML编辑窗口中对相应的XAML语句进行修改,最终结果如下:</p><p><img class="pimg" src="/upload/image/微信截图_20211203144623.jpg"/></p><pre style="overflow-x:auto;font-size: 15px;" class="brush:xml;toolbar:false;"><Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<ListView Name="listView1" MinWidth="280">
<ListView.View>
<GridView x:Name="gridView1">
<GridViewColumn Header="ContactID"></GridViewColumn>
<GridViewColumn Header="FirstName"></GridViewColumn>
<GridViewColumn Header="LastName"></GridViewColumn>
<GridViewColumn Header="EmailAddress"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<WrapPanel Grid.Row="1" Orientation="Horizontal"></WrapPanel>
<Button Grid.Row="2" HorizontalAlignment="Right" Click="button1_Click" Name="button1">Refresh</Button>
</Grid></pre><p><br/></p><p> 这里有几点又需要进行说明: </p><p> (1)容器控件Panel,现在界面中有两个容器型的控件一个是Grid,另一个是WrapPanel。它们都是容器型控件,不过表现上有所不同。 </p><p> (2)大家应该注意到了在WrapPanel及Button上面的Grid.Row="n",这个就是Attached Properties(附加属性)。这个属性的作用是用来设置WrapPanel及Button应该在父容器的什么位置。 Attached Properties的XAML用法就是在自己的属性设置地方直接使用容器的类型名称.容器属性名称(Grid.Row)设置对应的值。</p><p> (3)大家应该注意到类似与ListView.View及Grid.RowDefinitions用法,这个叫做Complex Properties(复杂属性)。 </p><p> (4)GridView x:Name="gridView1"</p><p> 如上面这段代码中的x:Name=" gridCitys "这种用法,叫做Markup Extensions(标记扩展),以轻松实现XAML页面属性赋值,资源引用,类型转换等操作。 </p><p> 例如我们这个示例中使用到的DataGrid对象,然而DataGrid对象又没有Name属性,于是有了Markup Extensions。这样当我们想定位一个没有名字属性的控件,直接为扩展一个名称出来,这个可太方便了。</p><p><br/></p><p> 7)现在我们的示例中TextBlock和TextBox不是成对出现的,为了实现比较友好的界面一般需要成对出现,而且要在同一水平线上面,不能换行,在WPF中不能使用绝对定位,那应该怎么实现呢?很简单,使用StackPanel面板。修改后的代码如下:</p><pre style="overflow-x:auto;font-size: 15px;" class="brush:xml;toolbar:false;"><WrapPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_ContactID" Text="ContactID:" />
<TextBox Name="textBox_ContactID" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_FirstName" Text="FirstName:" />
<TextBox Name="textBox_FirstName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_LastName" Text="LastName:" />
<TextBox Name="textBox_LastName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_EmailAddress" Text="EmailAddress:" />
<TextBox Name="textBox_EmailAddress" MinWidth="100" />
</StackPanel>
</WrapPanel></pre><p><br/></p><p> 8)在Visual Studio 2019中,按F5键,把我们的第一个WPF程序运行起来。然后,你在窗体的边缘随意的拉伸。如以下2图所示,不论窗体如何拉伸或缩小,控件会不断的改变位置——适应最小原则(如果想要让他固定下来的话。那就需要将WrapPanel换成其他的Panel就可以了),但是TextBlock和TextBox总是成对的在同一水平线的位置上。如下图所示:</p><p><img class="pimg" src="/upload/image/微信截图_20211203144259.gif"/></p><p><br/></p><p>最终xaml代码如下:</p><pre style="overflow-x: auto; font-size: 15px;" class="brush:xml;toolbar:false;"><Window x:Class="WpfApp.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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<ListView Name="listView1" MinWidth="280">
<ListView.View>
<GridView x:Name="gridView1">
<GridViewColumn Header="ContactID"></GridViewColumn>
<GridViewColumn Header="FirstName"></GridViewColumn>
<GridViewColumn Header="LastName"></GridViewColumn>
<GridViewColumn Header="EmailAddress"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<WrapPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_ContactID" Text="ContactID:" />
<TextBox Name="textBox_ContactID" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_FirstName" Text="FirstName:" />
<TextBox Name="textBox_FirstName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_LastName" Text="LastName:" />
<TextBox Name="textBox_LastName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_EmailAddress" Text="EmailAddress:" />
<TextBox Name="textBox_EmailAddress" MinWidth="100" />
</StackPanel>
</WrapPanel>
<Button Grid.Row="2" HorizontalAlignment="Right" Click="button1_Click" Name="button1">Refresh</Button>
</Grid>
</Window></pre>
ListView示例(一) - (十八)
经过前面的学习,今天我做一个比较综合的WPF程序示例,主要包括以下功能:
1) 查询功能。从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,然后展示到WPF的Window上的一个ListView上。
2) 数据联动功能。当鼠标左键选中ListView中的某一条记录时,在ListView框下面文本框中显示详细信息。
3) 修改功能。修改TextBox中的内容后,点击“更新”按钮,把修改后的数据保存到数据库中,同时与Listview联动。
第一步、建立一个WPF项目 可参考第一章内容《新建WPF工程》:/Course?Id=13§ion=2
第二步:安装EntityFramework 使用NuGet下载最新版的EntityFramework。在解决方案资源管理器中——>在项目WpfApp鼠标右键单击——>弹出一个菜单,选中“管理解决方案的NuGet程序包”,打开NuGet程序包管理界面。安装完如下:
第三步、WPF界面布局 1)在新建完WPF项目之后,WPF项目中有一个默认界面,将鼠标放在方框的边缘点击就会产生相应的分割线,我们先将窗体随意的分成三行,以后在XAML代码中再进行具体的调整。在添加完分割线之后,看一下下方的XAML代码区域,每个分割线都做为一行RowDefinition。如下图。
2)在XAML代码编辑界面中将我们刚才定义的三行,修改其高度,代码如下。
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
行 说明 第1行 设为*用来放置ListView,这样在程序的实际运行过程会尽可能的充满整个区域 第2行 设为Auto尽量紧凑排列,减少空间的占用(如果这一行中没有放任何控件的话,他会小到0,这样在界面上就不会显示。) 第3行 设为22固定值,只是用来放置按钮控件
说明:
如果是你经常做ASP.NET或是windows的开发,可能会形成一个习惯——直接从工具箱上把控件拖拽到需要的地方。 这样直接拖放控件的方式,VS会自动生成一个固定的坐标,但是这种方式在WPF中不推荐使用,在WPF中推荐使用 Canvas、StackPanel、WrapPanel、DockPanel和Grid面板组合使用来组装界面。
对于WPF的界面布局,有以下几点建议:
第一、控件的布局应该有容器来决定,而不是通过控件的margin属性来控制位置。
第二、控件应避免明确的定义具体的尺寸,因为显示器分辨率及windows窗体的大小都有可能随时改变,如果明确的定义尺寸。
当窗体变动后就会出现大面积的空白或是缺失。但为了控件功能及效果的展示,应该限定一个可接受的最大及最小尺寸。
通过MinWidth, MinHeight, MaxWidth, MaxHeight属性可以实现这一点。
第三、由于现在显示器分辨率非常多(1366×768、1600×900、、1980×1080等等),如果将界面元素位置设置成与屏幕坐标相关,这样做的话是会有风险的。
第四、容器应将有效空间共享给其子控件,这也是为了不在窗体调整后,遗留出大块的空余。
第五、容器嵌套使用,因为不同的容器,表现效果不同,必要时应结合使用。
3)接下来在工具箱中双击ListView,一个小框会出现在界面上。
4)接下来在工具箱中双击WrapPanel,又一个大框会出现在界面上。
5)再增加一个Button按钮。
6) 在拖放完了上面这些控件后,你会发觉当前界面有点乱了,这时刚才我们在顶层Grid上面的画的分割线就要起到作用了,让我们在XAML编辑窗口中对相应的XAML语句进行修改,最终结果如下:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<ListView Name="listView1" MinWidth="280">
<ListView.View>
<GridView x:Name="gridView1">
<GridViewColumn Header="ContactID"></GridViewColumn>
<GridViewColumn Header="FirstName"></GridViewColumn>
<GridViewColumn Header="LastName"></GridViewColumn>
<GridViewColumn Header="EmailAddress"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<WrapPanel Grid.Row="1" Orientation="Horizontal"></WrapPanel>
<Button Grid.Row="2" HorizontalAlignment="Right" Click="button1_Click" Name="button1">Refresh</Button>
</Grid>
这里有几点又需要进行说明:
(1)容器控件Panel,现在界面中有两个容器型的控件一个是Grid,另一个是WrapPanel。它们都是容器型控件,不过表现上有所不同。
(2)大家应该注意到了在WrapPanel及Button上面的Grid.Row="n",这个就是Attached Properties(附加属性)。这个属性的作用是用来设置WrapPanel及Button应该在父容器的什么位置。 Attached Properties的XAML用法就是在自己的属性设置地方直接使用容器的类型名称.容器属性名称(Grid.Row)设置对应的值。
(3)大家应该注意到类似与ListView.View及Grid.RowDefinitions用法,这个叫做Complex Properties(复杂属性)。
(4)GridView x:Name="gridView1"
如上面这段代码中的x:Name=" gridCitys "这种用法,叫做Markup Extensions(标记扩展),以轻松实现XAML页面属性赋值,资源引用,类型转换等操作。
例如我们这个示例中使用到的DataGrid对象,然而DataGrid对象又没有Name属性,于是有了Markup Extensions。这样当我们想定位一个没有名字属性的控件,直接为扩展一个名称出来,这个可太方便了。
7)现在我们的示例中TextBlock和TextBox不是成对出现的,为了实现比较友好的界面一般需要成对出现,而且要在同一水平线上面,不能换行,在WPF中不能使用绝对定位,那应该怎么实现呢?很简单,使用StackPanel面板。修改后的代码如下:
<WrapPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_ContactID" Text="ContactID:" />
<TextBox Name="textBox_ContactID" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_FirstName" Text="FirstName:" />
<TextBox Name="textBox_FirstName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_LastName" Text="LastName:" />
<TextBox Name="textBox_LastName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_EmailAddress" Text="EmailAddress:" />
<TextBox Name="textBox_EmailAddress" MinWidth="100" />
</StackPanel>
</WrapPanel>
8)在Visual Studio 2019中,按F5键,把我们的第一个WPF程序运行起来。然后,你在窗体的边缘随意的拉伸。如以下2图所示,不论窗体如何拉伸或缩小,控件会不断的改变位置——适应最小原则(如果想要让他固定下来的话。那就需要将WrapPanel换成其他的Panel就可以了),但是TextBlock和TextBox总是成对的在同一水平线的位置上。如下图所示:
最终xaml代码如下:
<Window x:Class="WpfApp.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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<ListView Name="listView1" MinWidth="280">
<ListView.View>
<GridView x:Name="gridView1">
<GridViewColumn Header="ContactID"></GridViewColumn>
<GridViewColumn Header="FirstName"></GridViewColumn>
<GridViewColumn Header="LastName"></GridViewColumn>
<GridViewColumn Header="EmailAddress"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<WrapPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_ContactID" Text="ContactID:" />
<TextBox Name="textBox_ContactID" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_FirstName" Text="FirstName:" />
<TextBox Name="textBox_FirstName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_LastName" Text="LastName:" />
<TextBox Name="textBox_LastName" MinWidth="100" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5,2,5,2">
<TextBlock Name="textBlock_EmailAddress" Text="EmailAddress:" />
<TextBox Name="textBox_EmailAddress" MinWidth="100" />
</StackPanel>
</WrapPanel>
<Button Grid.Row="2" HorizontalAlignment="Right" Click="button1_Click" Name="button1">Refresh</Button>
</Grid>
</Window>