全文涉及到的是C#和XAML
如果这两门语言并非你喜欢的语言,那可以关闭本网页了
- 本文介绍的是什么?
- 一个火车站点信息查询软件
- 本文涉及到的WPF基本知识
- Task
- async await
- WebClient
- 数据绑定
这基本知识其他blog会有这更详细的讲解,本文将不会详细介绍这些内容
- 实现的基本原理
- 通过webclient 获取 指定网页静态资源
- 分析静态资源,并提取火车的站点信息
- 编译环境和平台
- VS2012
- .NET4.5
先通过几张截图看看本文介绍的应用是什么
界面做的不是太好,但基本功能都已实现
界面的实现
- 界面中包含了一个静态资源 DataTemplate UITraninID
- 作为显示所有火车ID的List的ItemTemplat
- UIMainGrid 用于显示某火车的详细站点信息
- 包含一个Textblock和一个DataGrid,分别显示ID和详细站点
<Window x:Class="Train.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="450" Width="525" WindowStartupLocation="CenterScreen"> <Window.Resources> <DataTemplate x:Key="UITrainID"> <TextBlock Text="{Binding ID}" Foreground="Black" FontSize="17" Width="70" TextAlignment="Center" /> </DataTemplate> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="60"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Background="Black"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="140"/> </Grid.ColumnDefinitions> <TextBlock Text="欢迎" Foreground="White" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Button x:Name="UIOpenFile" BorderThickness="0" Foreground="White" Background="Transparent" Content="打开文件" Grid.Column="1" FontSize="20" Click="UIOpenFile_Click" /> <Button x:Name="UISave" BorderThickness="0" Foreground="White" Background="Transparent" Content="保存" Grid.Column="2" FontSize="20" Click="UISave_Click" /> <Button x:Name="UIAbout" BorderThickness="0" Foreground="White" Background="Transparent" Content="关于本应用" Grid.Column="3" FontSize="20" Click="UIAbout_Click" /> </Grid> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Background="LightSkyBlue"> <TextBlock Text="列车ID" FontSize="19" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <ListView x:Name="UIlist" ItemTemplate="{StaticResource ResourceKey=UITrainID}" BorderThickness="0" Grid.Row="1" SelectionChanged="UIlist_SelectionChanged"/> </Grid> <Grid x:Name="UIMainGrid" Grid.Column="1"> <Border BorderThickness="1,0,0,0" BorderBrush="Black" /> <Grid Margin="30,15,30,50"> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Background="LightGreen"> <TextBlock Text="{Binding ID}" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" /> </Grid> <Grid Background="AliceBlue" Grid.Row="1"> <DataGrid IsReadOnly="True" ItemsSource="{Binding All_station}" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Grid> </Grid> <Grid Grid.Column="1"> <ProgressBar x:Name="UIPro" Value="0" Background="Salmon" Height="40" Margin="86,0,0,0" VerticalAlignment="Bottom"/> <TextBlock x:Name="UItext" TextWrapping="Wrap" Text="100" VerticalAlignment="Top" FontSize="17" HorizontalAlignment="Left" Margin="100,33,0,0" /> <TextBlock Foreground="Green" HorizontalAlignment="Left" Margin="25,0,0,10" TextWrapping="Wrap" Text="进度" VerticalAlignment="Bottom" FontSize="17" FontWeight="Bold"/> </Grid> </Grid> </Grid> </Window>
下面设计详细
这是下文将会用到的几个静态资源
private static string send = "</div>";//站点信息结束标示符 private static string sbegin = "result-data";//站点信息开始标示符 private static string SiteUrl = "http://piao.huoche.com/checi/{0}/";//URL模板 private static string surl; public static List<TrainInfo> AllTrain = new List<TrainInfo>(); //所有信息
1.获取指定网页静态资源
public static List<station> GetWebData() { WebClient myWebClient = new WebClient(); //skip certificate error ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; try { // stream get html_sourcefile Stream myStream = myWebClient.OpenRead(surl); StreamReader sr = new StreamReader(myStream, System.Text.Encoding.GetEncoding("utf-8")); //get data var result = PickInfo(sr.ReadToEnd()); //close stream myStream.Close(); return result; } catch { return null; } }
通过OpenRead方法获取 指定url 的数据流
实体化StreamReader类,并调用ReadToEnd()方法,获取静态string资源
并调静态资源分析函数
返回指定网页的所有站点的一个 List<station>
2.分析网页源码
public static List<station> PickInfo(string s) { List<station> allstation = new List<station>(); int index_begin = s.IndexOf(sbegin); int index_end = s.IndexOf(send, index_begin); ) .Split('<', '>'); , value = ; ; i < stemp.Length; i++) { stemp[i] = stemp[i].Trim(); try { value = int.Parse(stemp[i]); } catch { continue; } if (value != n) continue; //while (stemp[i].Contains("td") || !ISChinese(stemp[i])) i++; i+=; station astation = new station { Name = stemp[i], Index = n }; i+=; astation.ArriveTime = stemp[i]; i+=; astation.LeaveTime = stemp[i]; i+=; astation.TimeSum = stemp[i]; i += ; allstation.Add(astation); n++; } return allstation; }
简单的字符串处理,代码写的并不是太好。。
3.我已经有了一个保存所有车次ID的文本,如何获取并显示所有火车信息
读取文本信息,对于每一ID,实体化一个 TrainInfo类,并加入到AllTrainList里面
TrainInfo 包含两个属性
- string ID
- list<station> all_station
通过调用异步方法GETDATA()
[网络不稳定因素可能导致调用该方法时占用大量时间,所以采用异步实现]
根据ID,生成一个URL连接,并new 一个task->GetWebData ,去获取该页面的数据
public static async Task<List<station>> GetData(string id) { Task<List<station>> task = new Task<List<station>>(GetWebData); surl = string.Format(SiteUrl,id); task.Start(); return await task; }
4.UI显示
UI主要有两个控件用于显示数据,分别是
- ListView,显示查询的所有火车的ID
- DataGrid,显示某个ID的所有站点信息
为什么不是每一个TrainInfo都对应一个DataGrid
在大量查询时,如果每个TrainInfo都对应一个DataGrid,将会占用大量内存
还有一个progressbar 用于显示当前数据的获取状态
具体实现如下
private async void UIOpenFile_Click(object sender, RoutedEventArgs e) { if (!Global.fileopen()) return; //showpro(); IdList.Clear(); UIPro.Maximum = Global.AllTrain.Count; UIPro.Value = ; foreach (var x in Global.AllTrain) { UItext.Text = string.Format(sGetInfo, x.ID) + "\n" + swait; x.All_station = await Global.GetData(x.ID); IdList.Add(new UITrainTextBlock { ID = x.ID }); UIPro.Value++; } UItext.Text = ""; //showdata(); }