.NET Framework WPF应用--主用于测试货物追踪
.NET Framework WPF应用
--主用于当前项目中测试货物追踪
1、新建WPF项目


2、对WPF布局 -暂时在MainWindow.xaml上布局

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.9*" MinHeight="190" />
<RowDefinition Height="0.1*" />
<RowDefinition Height="1.1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- 登录布局 -->
<Grid Grid.Row="0" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
FontWeight="Bold"
Text="接口Host:" />
<TextBox
Grid.Row="0"
Grid.Column="1"
MinHeight="20"
Text="{Binding Host}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
MinHeight="20"
FontWeight="Bold"
Text="账号:" />
<TextBox
Grid.Row="1"
Grid.Column="1"
MinHeight="20"
Text="{Binding UserName}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
MinHeight="20"
FontWeight="Bold"
Text="密码:" />
<TextBox
Grid.Row="2"
Grid.Column="1"
MinHeight="20"
Text="{Binding Password}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
MinHeight="20"
FontWeight="Bold"
Text="Token:" />
<TextBox
Grid.Row="3"
Grid.Column="1"
MinHeight="20"
IsEnabled="False"
Text="{Binding Token}" />
<Button
Grid.Row="0"
Grid.Column="2"
MinHeight="30"
MaxWidth="100"
Click="Login_Click"
Content="登录系统" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
FontWeight="Bold"
Text="{Binding LoginErrorMess}"
TextWrapping="Wrap">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<!-- 插入数据布局 -->
<Grid Grid.Row="2" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="0.3*" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.8*" />
<ColumnDefinition Width="0.1*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
FontWeight="Bold"
Text="坐标格式 合同id|经度|维度$合同id|经度|维度,各数据用|分割,每行用$分割,示例: 123|116.70985506003721|39.852990112588472$223|116.30856323242188|39.925624847412109 "
TextWrapping="Wrap" />
<TextBox
Grid.Row="1"
Grid.Column="0"
Height="Auto"
MinWidth="400"
MinHeight="200"
AcceptsReturn="True"
Text="{Binding Data}"
TextWrapping="Wrap" />
<StackPanel Grid.Row="0" Grid.Column="2">
<TextBlock
FontWeight="Bold"
Text="{Binding SendErrorMess}"
TextWrapping="Wrap">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
</TextBlock.Style>
</TextBlock>
<Button
MinHeight="20"
MaxWidth="100px"
Click="SubmitData_Click">
开始插入坐标
</Button>
</StackPanel>
<TextBox
Grid.Row="1"
Grid.Column="2"
Height="Auto"
MinWidth="400"
MinHeight="200"
AcceptsReturn="True"
Text="{Binding SubmitDataMess}"
TextWrapping="Wrap" />
</Grid>
</Grid>
Grid布局剖析:

--注意:宽高那里写成“数字*” 便于页面可以根据外框伸缩大小变动对应自身大小
3、WPF项目MainView.cs文件中编写MainWindow.xaml所需对应值(类似与vue中date()里写的字段),实现类似于vue的那种双向绑定

完善一下:
步骤③那里加入这个东西
步骤④那里绑定时OnPropertyCanged("")引号里不用再次写东西--会自动识别

继承INotifyPropertyChanged 为了实现双向绑定--然后客户端绑定对应的字段之改变时,这里会接收到改变的值
/// <summary> ///mianwindow绑定的viewmodel 继承INotifyPropertyChanged 实现双向绑定 /// </summary> public class MainView : INotifyPropertyChanged { //实现接口 public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// wpf双向绑定消息通知 /// </summary> /// <param name="propertyName">属性名称</param> private void OnPropertyCanged(string propertyName) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private string _host; private string _userName; private string _password; /// <summary> /// //前面输入的对应的host值 /// </summary> public string Host { get => _host; set { _host = value; OnPropertyCanged("Host"); } } /// <summary> /// //前面输入的对应的用户名值 /// </summary> public string UserName { get => _userName; set { _userName = value; OnPropertyCanged("UserName"); } } public string Password { get => _password; set { _password = value; OnPropertyCanged("Password"); } } private string _token; /// <summary> /// 登录token /// </summary> public string Token { get => _token; set { _token = value; OnPropertyCanged("Token"); } } public string _submitDataMess; /// <summary> /// 提交数据提示信息 /// </summary> public string SubmitDataMess { get => _submitDataMess; set { _submitDataMess = value; OnPropertyCanged("SubmitDataMess"); } } public string _sendErrorMess; /// <summary> /// 提交数据错误信息 /// </summary> public string SendErrorMess { get => _sendErrorMess; set { _sendErrorMess = value; OnPropertyCanged("ErrorMess"); } } public string _loginErrorMess; /// <summary> /// 登录错误信息 /// </summary> public string LoginErrorMess { get => _loginErrorMess; set { _loginErrorMess = value; OnPropertyCanged("LoginErrorMess"); } } private string data; /// <summary> /// 数据信息 /// </summary> public string Data { get => data; set { data = value; OnPropertyCanged("Data"); } } }
4、在MainWindow.xaml.cs上来编辑一些wpf页面中添加等点击事件的操作方法请求--调用api
4-1

/// <summary> /// httpclient 请求过期时间 /// </summary> int timeOut = 30; //放入请求头的token键名 public string tokenKey = "mytoken"; //声明一个全局MainView类--(里面是放着所需要的数据字段--方便下面用) public MainView MainView; //可以对MainWindow里的字段东西初始化 public MainWindow() { InitializeComponent(); MainView = new MainView(); MainView.Host = "http://localhost:5174/api"; MainView.UserName = "杨超凡"; MainView.Password = "123"; // 设置当前窗体(MainVindow.xaml)绑定数据--表示绑定的字段名都在MainView.cs这个类里 this.DataContext = MainView; }
4-1:编写对应的方法
注意:bs项目使用ajax请求webapi cs项目使用httpclient请求webapi
Client GET请求

// 客户端触发的事件 --调用api接口 /// <summary> /// 前台登录点击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Login_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrWhiteSpace(MainView.UserName) || string.IsNullOrWhiteSpace(MainView.Password) || string.IsNullOrWhiteSpace(MainView.Host) ) { MainView.LoginErrorMess = "请输入用户名或者密码"; } string loginUrl = MainView.Host + $"/login?userName={MainView.UserName}&pwd={MainView.Password}"; try { //bs项目使用ajax请求webapi cs项目使用httpclent请求webapi using (HttpClient client = new HttpClient()) { //请求api过期时间 client.Timeout = new TimeSpan(0, 0, timeOut); //发起get请求 返回请求结果--有token string response = client.GetAsync(loginUrl).Result.Content.ReadAsStringAsync().Result; if (!string.IsNullOrEmpty(response)) { wpfResultModel result = JsonConvert.DeserializeObject<wpfResultModel>(response); //序列化json if (result.code == ResultCode.Ok) { MainView.Token = result.data.token; MessageBox.Show("登录成功!"); } else { MainView.LoginErrorMess = "登录执行失败"; } } else { MainView.LoginErrorMess = "登录请求失败"; } } } catch (Exception ex) { MainView.LoginErrorMess = "出现错误,错误信息:" + ex.ToString(); } }
Client POST请求

public void Submit(MainView viewModel) { //使用task起一个线程,这样就可以动态的显示插入的消息 Task.Factory.StartNew(() => { viewModel.SubmitDataMess = ""; //因为多条数据每行是用$分割开输入的 List<string> dataList = viewModel.Data.Split('$').ToList(); for (int i = 0; i < dataList.Count; i++) { string[] data = dataList[i].Split('|'); if (data.Length != 3) { viewModel.SubmitDataMess = "数据:{dataList[i]}格式不正确" + " \r\n" + viewModel.SubmitDataMess; continue; } string subMitUrl = viewModel.Host + $"/Contract/ContractFreightLine/ContractFreightLineLngAndLatAdd?cId={data[0]}&lng={data[1]}&lat={data[2]}"; using (HttpClient client = new HttpClient()) { client.Timeout = new TimeSpan(0, 0, timeOut); client.DefaultRequestHeaders.Add(tokenKey, viewModel.Token); //在header头中加入token string result = client.PostAsync(subMitUrl, null).Result.Content.ReadAsStringAsync().Result; if (!string.IsNullOrEmpty(result)) { wpfResultModel resultModel = JsonConvert.DeserializeObject<wpfResultModel>(result); //序列化json if (resultModel.code == ResultCode.Ok) { viewModel.SubmitDataMess = $"数据:{dataList[i]}发送完毕, 等5秒钟后发送下一个" + " \r\n" + viewModel.SubmitDataMess; Thread.Sleep(5000); } else { viewModel.SubmitDataMess = $"数据:{dataList[i]}执行错误 错误信息:{resultModel.mess}" + " \r\n" + viewModel.SubmitDataMess; continue; } } } } }); }
此类完整代码:
/// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { /// <summary> /// httpclient 请求过期时间 /// </summary> int timeOut = 30; //放入请求头的token键名 public string tokenKey = "mytoken"; //声明一个全局MainView类--(里面是放着所需要的数据字段--方便下面用) public MainView MainView; //可以对MainWindow里的字段东西初始化 public MainWindow() { InitializeComponent(); MainView = new MainView(); MainView.Host = "http://localhost:5174/api/"; MainView.UserName = "杨超凡"; MainView.Password = "123"; // 设置当前窗体(MainVindow.xaml)绑定数据--表示绑定的字段名都在MainView.cs这个类里 http://localhost:5174/api/SystemBase/LoginManager/Login this.DataContext = MainView; } // 客户端触发的事件 --调用api接口 /// <summary> /// 前台登录点击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Login_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrWhiteSpace(MainView.UserName) || string.IsNullOrWhiteSpace(MainView.Password) || string.IsNullOrWhiteSpace(MainView.Host) ) { MainView.LoginErrorMess = "请输入用户名或者密码"; } string loginUrl = MainView.Host + $"SystemBase/LoginManager/Login?userName={MainView.UserName}&pwd={MainView.Password}"; try { //bs项目使用ajax请求webapi cs项目使用httpclent请求webapi using (HttpClient client = new HttpClient()) { //请求api过期时间 client.Timeout = new TimeSpan(0, 0, timeOut); //发起get请求 返回请求结果--有token string response = client.GetAsync(loginUrl).Result.Content.ReadAsStringAsync().Result; if (!string.IsNullOrEmpty(response)) { wpfResultModel result = JsonConvert.DeserializeObject<wpfResultModel>(response); //序列化json if (result.code == ResultCode.Ok) { MainView.Token = result.data.Token; MessageBox.Show("登录成功!"); } else { MainView.LoginErrorMess = "登录执行失败"; } } else { MainView.LoginErrorMess = "登录请求失败"; } } } catch (Exception ex) { MainView.LoginErrorMess = "出现错误,错误信息:" + ex.ToString(); } } //输入提交坐标数据 private void SubmitData_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(MainView.Data)) { MainView.SendErrorMess = "请输入要提交的坐标数据"; return; } if (!ContractFreightLineLngAndLatDeleteAll()) { MainView.SendErrorMess = MainView.SendErrorMess + " \r\n清除数据失败"; return; } //123|116.70985506003721|39.852990112588472$2|222|333$3|333|444$3|333|4444$4|4444|5555 Submit(MainView); } public void Submit(MainView viewModel) { //使用task起一个线程,这样就可以动态的显示插入的消息 Task.Factory.StartNew(() => { viewModel.SubmitDataMess = ""; //因为多条数据每行是用$分割开输入的 List<string> dataList = viewModel.Data.Split('$').ToList(); for (int i = 0; i < dataList.Count; i++) { string[] data = dataList[i].Split('|'); if (data.Length != 3) { viewModel.SubmitDataMess = "数据:{dataList[i]}格式不正确" + " \r\n" + viewModel.SubmitDataMess; continue; } string subMitUrl = viewModel.Host + $"SystemBase/ShipperContract/ContractFreightLineLngAndLatAdd?cId={data[0]}&lng={data[1]}&lat={data[2]}"; using (HttpClient client = new HttpClient()) { client.Timeout = new TimeSpan(0, 0, timeOut); client.DefaultRequestHeaders.Add(tokenKey, viewModel.Token); //在header头中加入token string result = client.PostAsync(subMitUrl, null).Result.Content.ReadAsStringAsync().Result; if (!string.IsNullOrEmpty(result)) { wpfResultModel resultModel = JsonConvert.DeserializeObject<wpfResultModel>(result); //序列化json if (resultModel.code == ResultCode.Ok) { viewModel.SubmitDataMess = $"数据:{dataList[i]}发送完毕, 等5秒钟后发送下一个" + " \r\n" + viewModel.SubmitDataMess; Thread.Sleep(5000); } else { viewModel.SubmitDataMess = $"数据:{dataList[i]}执行错误 错误信息:{resultModel.mess}" + " \r\n" + viewModel.SubmitDataMess; continue; } } } } }); } /// <summary> /// 清除数据 --只用与测试 /// </summary> /// <returns></returns> public bool ContractFreightLineLngAndLatDeleteAll() { if (string.IsNullOrEmpty(MainView.Token)) { MainView.SendErrorMess = "没有登录,请登录后在提交"; return false; } try { string deleteUrl = MainView.Host + $"SystemBase/ShipperContract/ContractFreightLineLngAndLatDeleteAll"; //bs项目使用ajax请求webapi cs项目使用httpclent请求webapi using (HttpClient client = new HttpClient()) { client.Timeout = new TimeSpan(0, 0, timeOut); client.DefaultRequestHeaders.Add(tokenKey, MainView.Token); //在header头中加入token string response = client.DeleteAsync(deleteUrl).Result.Content.ReadAsStringAsync().Result; if (!string.IsNullOrEmpty(response)) { wpfResultModel result = JsonConvert.DeserializeObject<wpfResultModel>(response); //序列化json if (result.code == ResultCode.Ok) { return true; } else { MainView.SendErrorMess = $"执行清除数据出现错误,详细信息:{result.mess}"; return false; } } else { MainView.SendErrorMess = "清除数据失败"; return false; } } } catch (Exception ex) { MainView.SendErrorMess = "没有登录,请登录后在提交" + ex.ToString(); return false; } } }
5、完成WPF项目效果

本文来自博客园,作者:じ逐梦,转载请注明原文链接:https://www.cnblogs.com/ZhuMeng-Chao/p/16362541.html

浙公网安备 33010602011771号