.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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了