邯郸wap网站建设费用,家具设计与工程就业前景,企业网站建设方案 word,html简单百度网页代码日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData)#xff0c;在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。
P.S#xff1a;DevExpress WinForms拥有180…日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData)在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。
P.SDevExpress WinForms拥有180组件和UI库能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序无论是Office风格的界面还是分析处理大批量的业务数据它都能轻松胜任
获取DevExpress v24.1正式版下载(Q技术交流532598169)
基本假设
随着时间的推移许多最初作为桌面应用程序的应用程序系统已经扩展为独立于任何原始客户端直接绑定模式的数据访问服务。例如web应用程序或移动前端可能在某个时候进入了人们的视野这就需要更广泛地看待数据访问架构。另一方面也许您的应用程序系统还没有经过这些步骤
无论哪种情况其想法都是将直接连接转移到数据库服务器例如使用Microsoft SQL Server的端口1433转移到不再由桌面应用程序负责的地方。一旦您的系统有多个客户端这可能是出于维护原因的需求或者可能是为了促进更清晰的体系结构。
出于本文演示的目的数据服务将非常简单。我们假设它使用Entity Framework Core实体框架核心进行数据访问但关键是数据访问在服务级别上不应该是困难的。同样我们假设在需要的时候给服务添加功能是很容易的——当然在这篇文章中我们还不会关注服务不能被触及的复杂场景。
我们做出的最后一个假设是该服务比Odata的服务更“通用”。这并不是说使用OData不好但是对于这个演示我们将不使用它。
演示存储库
您可以在GitHub存储库中找到这个演示的示例代码自述文件描述了如何运行示例。
后端 - 使用Entity Framework Core的ASP. NET Core WebAPI服务
后端项目称为DataService它是使用标准ASP. NET Core WebAPI模板创建的使用顶级语句和服务的“minimal API” 配置格式它不包含本演示所不需要的任何内容——这样您就可以专注于演示设置本身所需的代码。服务中有两个端点处理程序一个用于生成一些测试数据另一个用于查询数据。
第二个处理程序位于URL /data/OrderItems这是本文的重要处理程序。对于示例实现处理程序接受几个可选参数来支持跳过、获取和排序功能。代码很简单它从Entity Framework Core数据库上下文查询数据并使用标准的基于IQueryableT的助手来实现数据整形功能。TotalCount字段与数据一起返回因为我们在客户端需要这个字段来确定有多少数据可供查询。
app.MapGet(/data/OrderItems, async (
DataServiceDbContext dbContext,
int skip 0, int take 20,
string sortField Id, bool sortAscending true)
{
var source
dbContext.OrderItems.AsQueryable()
.OrderBy(sortField (sortAscending ? ascending : descending));
var items await source.Skip(skip).Take(take).ToListAsync();var totalCount await dbContext.OrderItems.CountAsync();return Results.Ok(new
{
Items items,
TotalCount totalCount
});
});
说得更抽象一点这个端点处理程序举例说明了数据服务中需要的服务功能以便向前端应用程序或专用组件(如data Grid)提供所需的信息。实现和支持的数据整形特性集各不相同但从逻辑上讲任何数据访问都需要一些沿着这些路线工作的端点。
前端 - 带有DevExpress数据网格的Windows Forms应用程序
在项目WinForms.Client中您将找到OrderItem类这是客户端使用的类型表示后端上的数据。但是请注意此类型与后端使用的类型不同如果将其与DataService中的OrderItem仔细比较您会发现前端类型与后端类型显示的实体框架核心构件不同特别是在前端类型的属性声明中没有virtual关键字。
在实际的应用程序中这些类型可能(很可能)差别更大。示例设置很简单引入数据类型只是为了演示但实际上后端持久类型和服务检索数据的前端模型之间的差异可能要明显得多。
在Windows Forms应用程序的MainForm中DevExpress GridControl组件配置了与OrderItem的属性相对应的列。该组件被绑定到表单上的VirtualServerModeSource实例该实例的RowType属性被设置为OrderItem这允许网格自动从数据源发现列。 为了获取数据VirtualServerModeSource至少使用两个事件处理程序(尽管根据具体情况其中一个是可选的)ConfigurationChanged和MoreRows事件处理程序的代码可以在MainForm.cs中找到。
当网格作为对用户交互的反应而改变其运行时配置的某些相关部分时例如当用户单击列标头应用排序时执行ConfigurationChanged处理程序。当初始获取操作返回一个结果表明有更多的数据可用时MoreRows处理程序就会出现。在这种情况下当用户滚动到当前加载的数据集的底部时网格将尝试检索更多的行。
在示例中虚拟数据源的加载逻辑封装在类VirtualServerModeDataLoader中该类由ConfigurationChanged事件处理程序实例化即在最终用户每次更改网格的运行时配置时实例化。加载器类在实例化时接收当前配置作为示例代码显示了如何提取排序细节并记住它们以供以后的应用程序使用。
public VirtualServerModeDataLoader(
VirtualServerModeConfigurationInfo configurationInfo)
{
// For instance, lets assume the backend supports sorting for just one field
if (configurationInfo.SortInfo?.Length 0)
{
SortField configurationInfo.SortInfo[0].SortPropertyName;
SortAscending !configurationInfo.SortInfo[0].IsDesc;
}
}public string SortField { get; set; } Id;
public bool SortAscending { get; set; } true;
在示例中从后端加载的数据被编码为JSON尽管gRPC/Protocol Buffers等不同的编码也同样有效。DataFetchResult类型为后端端点发布的结构建模包括TotalCount信息字段。
public class DataFetchResult
{
public ListOrderItem Items { get; set; } null!;
public int TotalCount { get; set; }
}
最后GetRowsAsync方法处理实际的数据检索。它在初始加载(从ConfigurationChanged处理程序)和进一步加载(从MoreRows处理程序)时都被调用但区别只是这些应用程序之间事件参数的CurrentRowCount字段不同。
HttpClient用于检索数据将参数作为skip、take和排序属性的URL参数传递。结果从JSON中反序列化并与moreRowsAvailable标志一起返回该标志由网格解释如前所述。
public TaskVirtualServerModeRowsTaskResult
GetRowsAsync(VirtualServerModeRowsEventArgs e)
{
return Task.Run(async ()
{
using var client new HttpClient();
var response await client.GetAsync(
${System.Configuration.ConfigurationManager.AppSettings[baseUrl]}/data/OrderItems?skip{e.CurrentRowCount}take{BatchSize}sortField{SortField}sortAscending{SortAscending});
response.EnsureSuccessStatusCode();
var responseBody await response.Content.ReadAsStringAsync();var dataFetchResult
JsonSerializer.DeserializeDataFetchResult(
responseBody, new JsonSerializerOptions
{
PropertyNameCaseInsensitive true
});if (dataFetchResult is null)
return new VirtualServerModeRowsTaskResult();var moreRowsAvailable
e.CurrentRowCount dataFetchResult.Items.Count dataFetchResult.TotalCount;return new VirtualServerModeRowsTaskResult(
dataFetchResult.Items, moreRowsAvailable);
}, e.CancellationToken);
}
这就完成了将数据网格绑定到独立服务的第一个实现。