经过前面的学习,今天我做一个比较综合的WPF程序示例,主要包括以下功能: 1) 查询功能。从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,然后展示到WPF的Window上的一个ListView上。 2) 数据联动功能。当鼠标左键选中ListView中的某一条记录时,在ListView框下面文本框中显示详细信息。 3) 修改功能。修改TextBox中的内容后,点击“更新”按钮,把修改后的数据保存到数据库中,同时与Listview联动。 第一步、建立一个WPF项目 打开Visual Studio 2013,在菜单上点击文件—>新建—>项目—>WPF应用程序。在弹出界面的“名称”对应的文本框中输入“WpfApp1”,然后点击“确定”按钮。如下图。 第二步:安装Entity Framework 1) 使用NuGet下载最新版的Entity Framework 6.1。在解决方案资源管理器中——>在项目WpfApp1上鼠标右键单击——>弹出一个菜单,选中“管理解决方案的NuGet程序包”,打开NuGet程序包管理界面。如下图。 2) 在NuGet程序包管理界面中搜索 Entity,找到最新版本Entity Framework,点击安装。如下图。 3) 安装完成之后,如下图。 第三步、WPF界面布局 1) 在新建完WPF项目之后,WPF项目中有一个默认界面。如下图。 2) 将鼠标放在方框的边缘点击就会产生相应的分割线。如下图。 3) 我们先将窗体随意的分成三行,以后在XAML代码中再进行具体的调整。在添加完分割线之后,看一下下方的XAML代码区域,每个分割线都做为一行RowDefinition。如下图。 4) 在XAML代码编辑界面中将我们刚才定义的三行,修改其高度。代码如下。 <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="22" /> 行 说明 第0行 设为*用来放置ListView,这样在程序的实际运行过程会尽可能的充满整个区域 第1行 设为Auto尽量紧凑排列,减少空间的占用(如果这一行中没有放任何控件的话,他会小到0,这样在界面上就不会显示。) 第2行 设为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等等),如果将界面元素位置设置成与屏幕坐标相关,这样做的话是会有风险的。 第四、容器应将有效空间共享给其子控件,这也是为了不在窗体调整后,遗留出大块的空余。 第五、容器嵌套使用,因为不同的容器,表现效果不同,必要时应结合使用。 5) 接下来在工具箱中双击ListView,一个小框会出现在界面上。 6) 接下来在工具箱中双击WrapPanel,又一个大框会出现在界面上。 7) 再增加一个Button按钮。 8) 在拖放完了上面这些控件后,你会发觉当前界面有点乱了,这时刚才我们在顶层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。这样当我们想定位一个没有名字属性的控件,直接为扩展一个名称出来,这个可太方便了。 9) 现在我们的示例中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> 10) 在Visual Studio 2013中,按F5键,把我们的第一个WPF程序运行起来。然后,你在窗体的边缘随意的拉伸。如以下2图所示,不论窗体如何拉伸或缩小,控件会不断的改变位置——适应最小原则(如果想要让他固定下来的话。那就需要将WrapPanel换成其他的Panel就可以了),但是TextBlock和TextBox总是成对的在同一水平线的位置上。如下图1(缩小)、图2(扩大)所示: 图1 图2 第四步、WPF后台逻辑代码编写 在后台用Entity Framework 6.1的Code First方式获取数据库中的数据。同时,在“刷新”按钮的方法中进行数据绑定。操作步骤如下: 1) 在“刷新”按钮上使用鼠标右键,单击,会弹出“属性”窗口。如下图。 2) 在“属性”窗口中点击右上角的闪电图标按钮,会出现事件窗口。在Click事件的文本框中进行双击,就会把按钮的Click事件添加到后台代码中。如下图。 3) 具体代码如下: public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Database.SetInitializer<TestDBContext>(null); } private void btnRefresh_Click(object sender, RoutedEventArgs e) { GetData(); } TestDBContext db = new TestDBContext(); protected void GetData() { List<S_City> list = db.S_City.ToList<S_City>(); listView1.ItemsSource = list; } private void menuPrism_Click(object sender, RoutedEventArgs e) { WindowPrismDemo1 win = new WindowPrismDemo1(); win.Show(); } } 4) 对象实体类。代码如下。 public class S_City { [Key] public long CityID { get; set; } public string CityName { get; set; } public string ZipCode { get; set; } public long ProvinceID { get; set; } public DateTime DateCreated { get; set; } public DateTime DateUpdated { get; set; } } public class TestDBContext : DbContext { public DbSet<S_City> S_City { get; set; } } 第五步、WPF前台界面与后台数据的Binding 写完了上面的代码之后,按F5,程序运行了起来,点“刷新”按钮却没有任何数据显示。这是由于后台数据与前面界面没有进行“绑定”,所以无法显示数据,接下来跟着我做。 1) 给GridViewColumn指明当前列对应于数据源的哪一项,可以通过DisplayMemberBinding属性来实现。其中Path后面的值便是上一步中所写的类S_City中指明属性名称。具体代码如下。 <ListView Name="listView1" MinWidth="280" Grid.Row="1" > <ListView.View> <GridView x:Name="gridView1"> <GridViewColumn Header="CityID" DisplayMemberBinding="{Binding Path=CityID}"></GridViewColumn> <GridViewColumn Header="CityName" DisplayMemberBinding="{Binding Path=CityName}"></GridViewColumn> <GridViewColumn Header="ZipCode" DisplayMemberBinding="{Binding Path=ZipCode}"></GridViewColumn> <GridViewColumn Header="ProvinceID" DisplayMemberBinding="{Binding Path=ProvinceID}"></GridViewColumn> <GridViewColumn Header="DateCreated" DisplayMemberBinding="{Binding Path=DateCreated}"></GridViewColumn> <GridViewColumn Header="DateUpdated" DisplayMemberBinding="{Binding Path=DateUpdated}"></GridViewColumn> </GridView> </ListView.View> </ListView> 2) 在Visual Studio 2013中按F5运行WPF程序,在程序运行起来之后,鼠标左键点击“刷新”按钮。你就可以看到如下图这样的画面了。 注意:如果运行时报以下错误信息: 异常:已引发: "The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269)." (System.InvalidOperationException) 引发了一个 System.InvalidOperationException: "The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269)." 解决方法: 具体请查看我前面代码中构造方法中以下语句。请注释掉就会报错,加上去就不会有问题。 Database.SetInitializer<TestDBContext>(null); 3) 当我们使用鼠标左键点击ListView中的记录时,里面的城市信息并没有同步映射到下面的文本框中。这个功能应该如何实现呢?。 4) 首先在WrapPanel元素中指明一个公共的上下文,可以通过增加属性 DataContext="{Binding ElementName=listView1,Path=SelectedItem}来实现。 5) 其次,对于需要显示相应信息的文本框,需要通过绑定TextBox元素中的Text属性实现,实现代码如下: <WrapPanel Grid.Row="2" Orientation="Horizontal" DataContext="{Binding ElementName=listView1,Path=SelectedItem}"> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_CityID" Text="CityID:" /> <TextBox Name="textBox_CityID" MinWidth="100" Text="{Binding CityID}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_CityName" Text="CityName:" /> <TextBox Name="textBox_CityName" MinWidth="100" Text="{Binding CityName}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_ZipCode" Text="ZipCode:" /> <TextBox Name="textBox_ZipCode" MinWidth="100" Text="{Binding ZipCode}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_ProvinceID" Text="ProvinceID:" /> <TextBox Name="textBox_ProvinceID" MinWidth="100" Text="{Binding ProvinceID}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_DateCreated" Text="DateCreated:" /> <TextBox Name="textBox_DateCreated" MinWidth="100" Text="{Binding DateCreated}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_DateUpdated" Text="DateUpdated:" /> <TextBox Name="textBox_DateUpdated" MinWidth="100" Text="{Binding DateUpdated}" /> </StackPanel> </WrapPanel> 6) 在Visual Studio 2013中按F5运行WPF程序,在程序运行起来之后,鼠标左键点击“刷新”按钮。在出现数据之后,使用鼠标左键点击ListView中的记录,你会发现文本框与ListView实现了联动。如下图。 第六步、数据更新 1) 在原来只放一个按钮的地方,需要要多放一个按钮,如果只是简单的放一个按钮,就会如下图,所示,两个按钮重叠在一起。 2) 我们需要在XAML窗口中加个一个面板窗口。代码如下。 <WrapPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right"> <Button HorizontalAlignment="Right" Name="btnRefresh" Height="22" VerticalAlignment="Top" Width="65" Click="btnRefresh_Click">刷新</Button> <Button HorizontalAlignment="Right" Name="btnUpdate" Height="22" VerticalAlignment="Top" Width="65" >更新</Button> </WrapPanel> 3) 给按钮btnUpdate添加一个Click事件,在Click事件中实现更新代码。代码如下。 private void btnUpdate_Click(object sender, RoutedEventArgs e) { long id = long.Parse(textBox_CityID.Text); var city = db.S_City.Where(c => c.CityID == id).OrderBy(c => c.CityID).FirstOrDefault(); city.CityID = id; city.CityName = textBox_CityName.Text; city.DateCreated = DateTime.Parse(textBox_DateCreated.Text); city.DateUpdated = DateTime.Parse(textBox_DateUpdated.Text); city.ProvinceID = long.Parse(textBox_ProvinceID.Text); city.ZipCode = textBox_ZipCode.Text; db.SaveChanges(); } 4) 选中一条记录,然后进行修改,更改之后,点击“更新”按钮。就可以把数据保存到数据库了。如下图。 5) 我们查询一下数据库,看一下数据是否已经更新到数据库里面了。如下图。 (本文转载自:http://www.cnblogs.com/chillsrc/) Loading... <p align="left">经过前面的学习,今天我做一个比较综合的WPF程序示例,主要包括以下功能:</p> 1) 查询功能。从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,然后展示到WPF的Window上的一个ListView上。 2) 数据联动功能。当鼠标左键选中ListView中的某一条记录时,在ListView框下面文本框中显示详细信息。 3) 修改功能。修改TextBox中的内容后,点击“更新”按钮,把修改后的数据保存到数据库中,同时与Listview联动。<!--more--> <h3 align="left"><strong>第一步、建立一个WPF项目</strong></h3> <p align="left">打开Visual Studio 2013,在菜单上点击文件—>新建—>项目—>WPF应用程序。在弹出界面的“名称”对应的文本框中输入“WpfApp1”,然后点击“确定”按钮。如下图。<strong> </strong></p> <p align="left"><span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2693-20150918133408258-593678371.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2693-20150918133408258-593678371.png" sizes="(max-width: 950px) 100vw, 950px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2693-20150918133408258-593678371-300x182.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2693-20150918133408258-593678371-768x466.png 768w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2693-20150918133408258-593678371.png 950w" alt="1456813009-2693-20150918133408258-593678371" width="950" height="577" style=""></a></span></p> <h3 align="left"><strong>第二步:安装Entity Framework</strong></h3> 1) 使用NuGet下载最新版的Entity Framework 6.1。在解决方案资源管理器中——>在项目WpfApp1上鼠标右键单击——>弹出一个菜单,选中“管理解决方案的NuGet程序包”,打开NuGet程序包管理界面。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2977-3-20150918133416226-48057161.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2977-3-20150918133416226-48057161.png" sizes="(max-width: 473px) 100vw, 473px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2977-3-20150918133416226-48057161-271x300.png 271w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-2977-3-20150918133416226-48057161.png 473w" alt="1456813009-2977-3-20150918133416226-48057161" width="473" height="523" style=""></a></span> <p align="left">2) 在NuGet程序包管理界面中搜索 Entity,找到最新版本Entity Framework,点击安装。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-9994-20150918133443023-1838620564.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-9994-20150918133443023-1838620564.png" sizes="(max-width: 896px) 100vw, 896px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-9994-20150918133443023-1838620564-300x200.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-9994-20150918133443023-1838620564-768x512.png 768w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-9994-20150918133443023-1838620564.png 896w" alt="1456813009-9994-20150918133443023-1838620564" width="896" height="597" style=""></a></span></p> <p align="left">3) 安装完成之后,如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-5430-20150918133450117-373213831.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-5430-20150918133450117-373213831.png" sizes="(max-width: 891px) 100vw, 891px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-5430-20150918133450117-373213831-300x202.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-5430-20150918133450117-373213831-768x517.png 768w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-5430-20150918133450117-373213831.png 891w" alt="1456813009-5430-20150918133450117-373213831" width="891" height="600" style=""></a></span></p> <h3 align="left"><strong> </strong><strong>第三步、WPF界面布局</strong></h3> 1) 在新建完WPF项目之后,WPF项目中有一个默认界面。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1840-20150918133500226-1122867063.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1840-20150918133500226-1122867063.png" sizes="(max-width: 757px) 100vw, 757px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1840-20150918133500226-1122867063-300x269.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1840-20150918133500226-1122867063.png 757w" alt="1456813009-1840-20150918133500226-1122867063" width="757" height="678" style=""></a></span> <p align="left">2) 将鼠标放在方框的边缘点击就会产生相应的分割线。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1728-20150918133505695-1588936663.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1728-20150918133505695-1588936663.png" sizes="(max-width: 491px) 100vw, 491px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1728-20150918133505695-1588936663-300x249.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813009-1728-20150918133505695-1588936663.png 491w" alt="1456813009-1728-20150918133505695-1588936663" width="491" height="408" style=""></a></span></p> <p align="left">3) 我们先将窗体随意的分成三行,以后在XAML代码中再进行具体的调整。在添加完分割线之后,看一下下方的XAML代码区域,每个分割线都做为一行RowDefinition。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-5801-20150918133513742-1839017722.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-5801-20150918133513742-1839017722.png" sizes="(max-width: 698px) 100vw, 698px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-5801-20150918133513742-1839017722-300x251.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813012-5801-20150918133513742-1839017722.png 698w" alt="1456813012-5801-20150918133513742-1839017722" width="698" height="583" style=""></a></span></p> <p align="left"> 4) 在XAML代码编辑界面中将我们刚才定义的三行,修改其高度。代码如下。</p> <pre class="lang:default decode:true "><RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="22" /></pre> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td valign="top" width="149"> <p align="left"><strong>行</strong></p> </td> <td valign="top" width="419"> <p align="left"><strong>说明</strong></p> </td> </tr> <tr> <td valign="top" width="149"> <p align="left">第0行</p> </td> <td valign="top" width="419"> <p align="left">设为*用来放置ListView,这样在程序的实际运行过程会尽可能的充满整个区域</p> </td> </tr> <tr> <td valign="top" width="149"> <p align="left">第1行</p> </td> <td valign="top" width="419"> <p align="left">设为Auto尽量紧凑排列,减少空间的占用(如果这一行中没有放任何控件的话,他会小到0,这样在界面上就不会显示。)</p> </td> </tr> <tr> <td valign="top" width="149"> <p align="left">第2行</p> </td> <td valign="top" width="419"> <p align="left">设为22固定值,只是用来放置按钮控件</p> </td> </tr> </tbody> </table> 说明: 如果是你经常做ASP.NET或是windows的开发,可能会形成一个习惯——直接从工具箱上把控件拖拽到需要的地方。 这样直接拖放控件的方式,VS会自动生成一个固定的坐标,但是这种方式在WPF中不推荐使用,在WPF中推荐使用 Canvas、StackPanel、WrapPanel、DockPanel和Grid面板组合使用来组装界面。 对于WPF的界面布局,有以下几点建议: 第一、控件的布局应该有容器来决定,而不是通过控件的margin属性来控制位置。 第二、控件应避免明确的定义具体的尺寸,因为显示器分辨率及windows窗体的大小都有可能随时改变,如果明确的定义尺寸。 当窗体变动后就会出现大面积的空白或是缺失。但为了控件功能及效果的展示,应该限定一个可接受的最大及最小尺寸。 通过MinWidth, MinHeight, MaxWidth, MaxHeight属性可以实现这一点。 第三、由于现在显示器分辨率非常多(1366×768、1600×900、、1980×1080等等),如果将界面元素位置设置成与屏幕坐标相关,这样做的话是会有风险的。 第四、容器应将有效空间共享给其子控件,这也是为了不在窗体调整后,遗留出大块的空余。 第五、容器嵌套使用,因为不同的容器,表现效果不同,必要时应结合使用。 <p align="left">5) 接下来在工具箱中双击ListView,一个小框会出现在界面上。</p> <p align="left">6) 接下来在工具箱中双击WrapPanel,又一个大框会出现在界面上。</p> <p align="left">7) 再增加一个Button按钮。</p> <p align="left">8) 在拖放完了上面这些控件后,你会发觉当前界面有点乱了,这时刚才我们在顶层Grid上面的画的分割线就要起到作用了,让我们在XAML编辑窗口中对相应的XAML语句进行修改,最终结果如下:</p> <pre class="lang:default decode:true "><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> 这里有几点又需要进行说明: (1)容器控件Panel,现在界面中有两个容器型的控件一个是Grid,另一个是WrapPanel。它们都是容器型控件,不过表现上有所不同。 (2)大家应该注意到了在WrapPanel及Button上面的Grid.Row="n",这个就是Attached Properties(附加属性)。这个属性的作用是用来设置WrapPanel及Button应该在父容器的什么位置。 Attached Properties的XAML用法就是在自己的属性设置地方直接使用容器的类型名称.容器属性名称(Grid<strong>.</strong>Row)设置对应的值。 (3)大家应该注意到类似与ListView.View及Grid.RowDefinitions用法,这个叫做Complex Properties(复杂属性)。 <p align="left">(4)<GridView x:Name="gridView1"></p> 如上面这段代码中的x:Name=" gridCitys "这种用法,叫做Markup Extensions(标记扩展),以轻松实现XAML页面属性赋值,资源引用,类型转换等操作。 例如我们这个示例中使用到的DataGrid对象,然而DataGrid对象又没有Name属性,于是有了Markup Extensions。这样当我们想定位一个没有名字属性的控件,直接为扩展一个名称出来,这个可太方便了。 <p align="left">9) 现在我们的示例中TextBlock和TextBox不是成对出现的,为了实现比较友好的界面一般需要成对出现,而且要在同一水平线上面,不能换行,在WPF中不能使用绝对定位,那应该怎么实现呢?很简单,使用StackPanel面板。修改后的代码如下:</p> <pre class="lang:default decode:true "><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 align="left">10) 在Visual Studio 2013中,按F5键,把我们的第一个WPF程序运行起来。然后,你在窗体的边缘随意的拉伸。如以下2图所示,不论窗体如何拉伸或缩小,控件会不断的改变位置——适应最小原则(如果想要让他固定下来的话。那就需要将WrapPanel换成其他的Panel就可以了),但是TextBlock和TextBox总是成对的在同一水平线的位置上。如下图1(缩小)、图2(扩大)所示: <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-8510-20150918133531101-1509832811.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-8510-20150918133531101-1509832811.png" sizes="(max-width: 414px) 100vw, 414px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813012-8510-20150918133531101-1509832811-300x250.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813012-8510-20150918133531101-1509832811.png 414w" alt="1456813012-8510-20150918133531101-1509832811" width="414" height="345" style=""></a></span></p> <p style="text-align: center;" align="left"> 图1</p> <p align="left"><span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-6032-20150918133541820-1448035749.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-6032-20150918133541820-1448035749.png" sizes="(max-width: 573px) 100vw, 573px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-6032-20150918133541820-1448035749-300x181.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-6032-20150918133541820-1448035749.png 573w" alt="1456813013-6032-20150918133541820-1448035749" width="573" height="346" style=""></a></span></p> <p style="text-align: center;" align="left"> 图2</p> <h3 align="left"><strong>第四步、WPF后台逻辑代码编写</strong></h3> <p align="left">在后台用Entity Framework 6.1的Code First方式获取数据库中的数据。同时,在“刷新”按钮的方法中进行数据绑定。操作步骤如下:</p> <p align="left">1) 在“刷新”按钮上使用鼠标右键,单击,会弹出“属性”窗口。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514.png" sizes="(max-width: 300px) 100vw, 300px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514-150x150.png 150w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514-200x200.png 200w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514-320x320.png 320w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-5011-20150921153950194-126924514.png 300w" alt="1456813013-5011-20150921153950194-126924514" width="300" height="300" style=""></a></span></p> <p align="left">2) 在“属性”窗口中点击右上角的闪电图标按钮,会出现事件窗口。在Click事件的文本框中进行双击,就会把按钮的Click事件添加到后台代码中。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-1523-20150921153957022-481945941.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-1523-20150921153957022-481945941.png" sizes="(max-width: 298px) 100vw, 298px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-1523-20150921153957022-481945941-193x300.png 193w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-1523-20150921153957022-481945941.png 298w" alt="1456813013-1523-20150921153957022-481945941" width="298" height="463" style=""></a></span></p> <p align="left">3) 具体代码如下:</p> <pre class="lang:default decode:true ">public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Database.SetInitializer<TestDBContext>(null); } private void btnRefresh_Click(object sender, RoutedEventArgs e) { GetData(); } TestDBContext db = new TestDBContext(); protected void GetData() { List<S_City> list = db.S_City.ToList<S_City>(); listView1.ItemsSource = list; } private void menuPrism_Click(object sender, RoutedEventArgs e) { WindowPrismDemo1 win = new WindowPrismDemo1(); win.Show(); } }</pre> 4) 对象实体类。代码如下。 <pre class="lang:default decode:true">public class S_City { [Key] public long CityID { get; set; } public string CityName { get; set; } public string ZipCode { get; set; } public long ProvinceID { get; set; } public DateTime DateCreated { get; set; } public DateTime DateUpdated { get; set; } } public class TestDBContext : DbContext { public DbSet<S_City> S_City { get; set; } }</pre> <h3 align="left"><strong>第五步、WPF前台界面与后台数据的Binding</strong></h3> <p align="left">写完了上面的代码之后,按F5,程序运行了起来,点“刷新”按钮却没有任何数据显示。这是由于后台数据与前面界面没有进行“绑定”,所以无法显示数据,接下来跟着我做。</p> <p align="left">1) 给GridViewColumn指明当前列对应于数据源的哪一项,可以通过DisplayMemberBinding属性来实现。其中Path后面的值便是上一步中所写的类S_City中指明属性名称。具体代码如下。</p> <pre class="lang:default decode:true "><ListView Name="listView1" MinWidth="280" Grid.Row="1" > <ListView.View> <GridView x:Name="gridView1"> <GridViewColumn Header="CityID" DisplayMemberBinding="{Binding Path=CityID}"></GridViewColumn> <GridViewColumn Header="CityName" DisplayMemberBinding="{Binding Path=CityName}"></GridViewColumn> <GridViewColumn Header="ZipCode" DisplayMemberBinding="{Binding Path=ZipCode}"></GridViewColumn> <GridViewColumn Header="ProvinceID" DisplayMemberBinding="{Binding Path=ProvinceID}"></GridViewColumn> <GridViewColumn Header="DateCreated" DisplayMemberBinding="{Binding Path=DateCreated}"></GridViewColumn> <GridViewColumn Header="DateUpdated" DisplayMemberBinding="{Binding Path=DateUpdated}"></GridViewColumn> </GridView> </ListView.View> </ListView></pre> <p align="left">2) 在Visual Studio 2013中按F5运行WPF程序,在程序运行起来之后,鼠标左键点击“刷新”按钮。你就可以看到如下图这样的画面了。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-7794-20150921154031725-275487127.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-7794-20150921154031725-275487127.png" sizes="(max-width: 535px) 100vw, 535px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813013-7794-20150921154031725-275487127-300x231.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813013-7794-20150921154031725-275487127.png 535w" alt="1456813013-7794-20150921154031725-275487127" width="535" height="412" style=""></a></span></p> <p align="left">注意:如果运行时报以下错误信息:</p> 异常:已引发: "The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269)." (System.InvalidOperationException) 引发了一个 System.InvalidOperationException: "The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269)." 解决方法: 具体请查看我前面代码中构造方法中以下语句。请注释掉就会报错,加上去就不会有问题。 Database.SetInitializer<TestDBContext>(null); 3) 当我们使用鼠标左键点击ListView中的记录时,里面的城市信息并没有同步映射到下面的文本框中。这个功能应该如何实现呢?。 <p align="left">4) 首先在WrapPanel元素中指明一个公共的上下文,可以通过增加属性 DataContext="{Binding ElementName=listView1,Path=SelectedItem}来实现。</p> <p align="left">5) 其次,对于需要显示相应信息的文本框,需要通过绑定TextBox元素中的Text属性实现,实现代码如下:</p> <pre class="lang:default decode:true "><WrapPanel Grid.Row="2" Orientation="Horizontal" DataContext="{Binding ElementName=listView1,Path=SelectedItem}"> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_CityID" Text="CityID:" /> <TextBox Name="textBox_CityID" MinWidth="100" Text="{Binding CityID}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_CityName" Text="CityName:" /> <TextBox Name="textBox_CityName" MinWidth="100" Text="{Binding CityName}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_ZipCode" Text="ZipCode:" /> <TextBox Name="textBox_ZipCode" MinWidth="100" Text="{Binding ZipCode}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_ProvinceID" Text="ProvinceID:" /> <TextBox Name="textBox_ProvinceID" MinWidth="100" Text="{Binding ProvinceID}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_DateCreated" Text="DateCreated:" /> <TextBox Name="textBox_DateCreated" MinWidth="100" Text="{Binding DateCreated}" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="5,2,5,2"> <TextBlock Name="textBlock_DateUpdated" Text="DateUpdated:" /> <TextBox Name="textBox_DateUpdated" MinWidth="100" Text="{Binding DateUpdated}" /> </StackPanel> </WrapPanel></pre> <p align="left">6) 在Visual Studio 2013中按F5运行WPF程序,在程序运行起来之后,鼠标左键点击“刷新”按钮。在出现数据之后,使用鼠标左键点击ListView中的记录,你会发现文本框与ListView实现了联动。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-5513-20150921154054990-1430190793.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-5513-20150921154054990-1430190793.png" sizes="(max-width: 601px) 100vw, 601px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-5513-20150921154054990-1430190793-300x173.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813015-5513-20150921154054990-1430190793.png 601w" alt="1456813015-5513-20150921154054990-1430190793" width="601" height="347" style=""></a></span></p> <h3 align="left"><strong>第六步、数据更新 </strong></h3> <p align="left">1) 在原来只放一个按钮的地方,需要要多放一个按钮,如果只是简单的放一个按钮,就会如下图,所示,两个按钮重叠在一起。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7957-20150921154104959-959824646.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7957-20150921154104959-959824646.png" sizes="(max-width: 620px) 100vw, 620px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7957-20150921154104959-959824646-300x47.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7957-20150921154104959-959824646.png 620w" alt="1456813015-7957-20150921154104959-959824646" width="620" height="98" style=""></a></span></p> <p align="left">2) 我们需要在XAML窗口中加个一个面板窗口。代码如下。</p> <pre class="lang:default decode:true "><WrapPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right"> <Button HorizontalAlignment="Right" Name="btnRefresh" Height="22" VerticalAlignment="Top" Width="65" Click="btnRefresh_Click">刷新</Button> <Button HorizontalAlignment="Right" Name="btnUpdate" Height="22" VerticalAlignment="Top" Width="65" >更新</Button> </WrapPanel></pre> 3) 给按钮btnUpdate添加一个Click事件,在Click事件中实现更新代码。代码如下。 <pre class="lang:default decode:true ">private void btnUpdate_Click(object sender, RoutedEventArgs e) { long id = long.Parse(textBox_CityID.Text); var city = db.S_City.Where(c => c.CityID == id).OrderBy(c => c.CityID).FirstOrDefault(); city.CityID = id; city.CityName = textBox_CityName.Text; city.DateCreated = DateTime.Parse(textBox_DateCreated.Text); city.DateUpdated = DateTime.Parse(textBox_DateUpdated.Text); city.ProvinceID = long.Parse(textBox_ProvinceID.Text); city.ZipCode = textBox_ZipCode.Text; db.SaveChanges(); }</pre> 4) 选中一条记录,然后进行修改,更改之后,点击“更新”按钮。就可以把数据保存到数据库了。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7414-20150921154135881-681408607.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7414-20150921154135881-681408607.png" sizes="(max-width: 598px) 100vw, 598px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7414-20150921154135881-681408607-300x172.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7414-20150921154135881-681408607.png 598w" alt="1456813015-7414-20150921154135881-681408607" width="598" height="342" style=""></a></span> 5) 我们查询一下数据库,看一下数据是否已经更新到数据库里面了。如下图。 <span class="external-link"><a class="no-external-link" href="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7349-20150921154149647-218326441.png" target="_blank"><i data-feather="external-link"></i><img class="attachment-full size-full aligncenter" src="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7349-20150921154149647-218326441.png" sizes="(max-width: 588px) 100vw, 588px" srcset="http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7349-20150921154149647-218326441-300x36.png 300w, http://www.xiaoten.com/usr/uploads/2016/03/1456813015-7349-20150921154149647-218326441.png 588w" alt="1456813015-7349-20150921154149647-218326441" width="588" height="70" style=""></a></span> (本文转载自:http://www.cnblogs.com/chillsrc/) © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏