WinForm(十一)用户控件

winform+api是一种对接数据模式,在本例中,为了方便,开发两个天生具有与后台api对接的用例控件,并且把他们封闭成单独控件,以供多次使用。

提示:此实例不是生产使用,仅作演示,有不完善地方,重点关注流程和自定义控件。

本例为API Server,用户控件项目,使用控件项目。

API Server端:

api端主要是根据提交上来的请求,组装成一个sql,查询一个内存sqlite数据库(请注意这里没有做sql注入处理)

using Dapper;using Microsoft.Data.Sqlite;using System.Data;using System.Data.Common;using System.Net;using System.Text;using System.Text.Encodings.Web;using System.Text.Unicode;using System.Web;var builder = WebApplication.CreateBuilder(args);var connection = new SqliteConnection(“Data Source=InMemorySample;Mode=Memory;Cache=Shared”);await InitDataAsync();async Task InitDataAsync(){await connection.OpenAsync();await connection.ExecuteAsync(“create table type(ID INTEGER primary key,Name text,Category INTEGER);”);await connection.ExecuteAsync(“insert into main.type(ID,Name,Category) values(1,’AliPay’,1),(2,’MiroPay’,1),(3,’PayPay’,2);”);await connection.ExecuteAsync(“create table [order](ID INTEGER primary key,Name text,Price real,Quantity integer);”);await connection.ExecuteAsync(“insert into [order](ID,Name,Price,Quantity) values(1,’产品A’,21.15,12),(2,’产品B’,32.45,23),(3,’产品C’,43.45,23);”);}builder.Services.AddSingleton(connection);builder.Services.AddResponseCaching();builder.Services.AddSingleton();var app = builder.Build();app.UseResponseCaching();app.Use(async (context, next) =>{context.Response.GetTypedHeaders().CacheControl =new Microsoft.Net.Http.Headers.CacheControlHeaderValue(){Public = true,MaxAge = TimeSpan.FromHours(1)};context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] =new string[] { “Accept-Encoding” };await next();});app.MapGet(“/parame/{dataSource}”, async (IParameService parameService, string dataSource, string fields, string conditions) =>{var list = await parameService.GetParamesAsync(dataSource, fields, conditions);return TypedResults.Json(list, new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = false });});app.Run();public interface IParameService{Task GetParamesAsync(string dataSource, string fields, string conditions);}public class ParameService : IParameService{private readonly ILogger _logger;private readonly IDbConnection _db;public ParameService(ILogger logger, IDbConnection db){_logger = logger;_db = db;}public async Task GetParamesAsync(string dataSource, string fields, string conditions){var sql = #34;select {fields} from [{dataSource}]”;if (conditions != null && conditions.Length > 0){var whereBuilder = new StringBuilder(” where “);var conditionArr = conditions.Split(new string[] { “(“, “),(“, “)” }, StringSplitOptions.RemoveEmptyEntries);foreach (var condition in conditionArr){var arr = condition.Split(new string[] { “,” }, StringSplitOptions.RemoveEmptyEntries);whereBuilder.Append(#34; {arr[0]} {arr[1]} ‘{arr[2]}’ and”);}sql += whereBuilder.ToString().Substring(0, whereBuilder.Length – 3);}_logger.LogInformation(sql);return await _db.QueryAsync(sql); }}

用户控件端:

用户控件有一个公共部分,分别处理两类控件ListControl和DataGridView控件,思路都是从控件上拿到相应的属性数据,然后组装http请求,取回数据,绑定到控件上。

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing.Design;using System.Linq;using System.Net.Http;using System.Security.Policy;using System.Text;using System.Text.Json;using System.Threading.Tasks;using System.Web;namespace GSWControls{public static class ControlExpand{static HttpClient _httpClient = new HttpClient();public static async Task DBControlInit(this ListControl control, string url, string dataSourceName, List? conditions){if (!control.IsAncestorSiteInDesignMode){if (!string.IsNullOrWhiteSpace(url) && !string.IsNullOrWhiteSpace(dataSourceName) && !string.IsNullOrWhiteSpace(control.DisplayMember) && !string.IsNullOrWhiteSpace(control.ValueMember)){url = #34;{url.TrimEnd(‘/’, ”)}/{dataSourceName}?fields={Uri.EscapeDataString(control.ValueMember)},{Uri.EscapeDataString(control.DisplayMember)}”;if (conditions != null && conditions.Count > 0){var arr = conditions.Select(s => #34;({s.Name},{s.Symbol},{s.Value})”).ToArray();url += “&conditions=” + Uri.EscapeDataString(string.Join(‘,’, arr));}var content = await _httpClient.GetStringAsync(url);var table = JsonToDataTable(content);control.DataSource = table;}}}static DataTable JsonToDataTable(string json){var table = new DataTable();var list = JsonSerializer.Deserialize<IList>(json);var columns = list?.First().Select(d => d.Key);if (list != null && columns != null){foreach (var item in columns){table.Columns.Add(item);}foreach (var item in list){table.Rows.Add(item.Values.ToArray());}}return table;}public static async Task DBGridInit(this DataGridView control, string url, string dataSourceName, List? conditions){if (!control.IsAncestorSiteInDesignMode){if (!string.IsNullOrWhiteSpace(url) && !string.IsNullOrWhiteSpace(dataSourceName) && control.Columns.Count > 0){var fieldList = new List();foreach (DataGridViewColumn column in control.Columns){fieldList.Add(column.DataPropertyName);}url = #34;{url.TrimEnd(‘/’, ”)}/{dataSourceName}?fields={Uri.EscapeDataString(string.Join(‘,’, fieldList))}”;if (conditions != null && conditions.Count > 0){var arr = conditions.Select(s => #34;({s.Name},{s.Symbol},{s.Value})”).ToArray();url += “&conditions=” + Uri.EscapeDataString(string.Join(‘,’, arr));}var content = await _httpClient.GetStringAsync(url);var table = JsonToDataTable(content);control.DataSource = table;}}}}public class DBCondition{[Browsable(true)][Description(“查询条件名称”), Category(“数据”), DefaultValue(“”)][DisplayName]public string? Name { get; set; }[Browsable(true)][Description(“条件符号”), Category(“数据”), DefaultValue(“”)]public string? Symbol { get; set; }[Browsable(true)][Description(“查询条件值”), Category(“数据”), DefaultValue(“”)]public string? Value { get; set; }}}

DBComBox控件:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;namespace GSWControls{[ToolboxItem(true)][ToolboxBitmap(typeof(DBComBox), “gcom.png”)]public class DBComBox : ComboBox{ [Browsable(true)][Description(“后端Url”), Category(“远程数据”), DefaultValue(“”)]public string? Url { get; set; }[Browsable(true)][Description(“访问Url后端数据源名称”), Category(“远程数据”), DefaultValue(“”)]public string? DataSourceName { get; set; }[Browsable(true)][Description(“查询数据源条件参数”), Category(“远程数据”), DefaultValue(“”)][DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]public List? Conditions { get; set; } = new List();protected async override void CreateHandle(){base.CreateHandle();if (!string.IsNullOrWhiteSpace(Url) && !string.IsNullOrWhiteSpace(DataSourceName) && Conditions != null){await this.DBControlInit(Url, DataSourceName, Conditions);}}}}

DBDataGridView控件:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;namespace GSWControls{[ToolboxItem(true)][ToolboxBitmap(typeof(DBDataGridView), “ggrid.png”)]public class DBDataGridView : DataGridView{[Browsable(true)][Description(“后端Url”), Category(“远程数据”), DefaultValue(“”)]public string? Url { get; set; }[Browsable(true)][Description(“访问Url后端数据源名称”), Category(“远程数据”), DefaultValue(“”)]public string? DataSourceName { get; set; }[Browsable(true)][Description(“查询数据源条件参数”), Category(“远程数据”), DefaultValue(“”)][DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]public List? Conditions { get; set; } = new List();protected async override void CreateHandle(){base.CreateHandle();if (!string.IsNullOrWhiteSpace(Url) && !string.IsNullOrWhiteSpace(DataSourceName) && Conditions != null){await this.DBGridInit(Url, DataSourceName, Conditions);}}}}

上面的属性都是为了在VS的工具箱或在属性管理器里,让自定义控件看起起来与官方控件一样。

使用控件项目:

使用项目很简单,就是完成布局,设置一下属性就可以了。

DBComBox的控件设置

查询条件设置(这里没有处理条件间的组合)

DBDataGridView的属性设置,DataGridView的列是设置在控件本身的更中的,这里就不切图了。

这个组合查询条件

最后运行结果:

本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系admin#jikehao.com删除。
(0)
极客号的头像极客号
上一篇 2022年 10月 2日
下一篇 2022年 10月 2日

相关推荐

合作联系:1152QQ041010