学习地址1:https://pan.baidu.com/s/1qOyFstIuAnTIlBo0-K1YDg 提取码: 68vv
学习地址2:https://share.weiyun.com/VAU3sFU2 密码:9cqtcj
WPF 主要编程模型通过托管代码公开。 在 WPF 的早期设计阶段,曾有过大量关于如何界定系统的托管组件和非托管组件的争论。 CLR 提供一系列的功能,可以提高开发效率和可靠性(包括内存管理、错误处理和通用类型系统等),但这是需要付出代价的。
PresentationFramework、PresentationCore 和 milcore是 WPF 的主要代码部分。 在这些组件中,只有一个是非托管组件 - milcore。 milcore 是以非托管代码编写的,目的是实现与 DirectX 的紧密集成。 WPF 中的所有显示均通过 DirectX 引擎完成,因此硬件和软件呈现都很高效。 WPF 还要求对内存和执行进行精细控制。 milcore 中的组合引擎受性能影响极大,需要放弃 CLR 的许多优点来提高性能。
生成 WPF 时使用的主要体系结构原理之一是首选属性而不是方法或事件。 属性具有声明性,可更方便地指定用途而不是操作。 它还支持模型驱动或数据驱动的系统,以显示用户界面内容。 这种理念的预期效果是创建更多可以绑定到的属性,从而更好地控制应用程序的行为。
public class PaginationResourceParamaters
{
private int _pageNumber = 1;
public int PageNumber
{
get
{
return _pageNumber;
}
set
{
if (value >= 1)
{
_pageNumber = value;
}
}
}
private int _pageSize = 10;
const int maxPageSize = 50;
public int PageSize
{
get
{
return _pageSize;
}
set
{
if (value >= 1)
{
_pageSize = (value > maxPageSize) ? maxPageSize : value;
}
}
}
}
控件的最重要功能是模板化。 如果将 WPF 的组合系统视为一个保留模式绘制系统,则控件可通过模板化以一种参数化的声明性方式描述其绘制。 ControlTemplate 实际上只是用于创建一组子元素的脚本,绑定到由控件提供的属性。
if (!string.IsNullOrWhiteSpace(orderBy))
{
if(orderBy.ToLowerInvariant() == "originalprice")
{
result = result.OrderBy(t => t.OriginalPrice);
}
//result.ApplySort(orderBy, _mappingDictionary);
}
文件创建完成,回到旅游路线参数处理器文件,我们把分页相关的代码全部剪切到刚刚创建的新文件中。
public class PaginationResourceParamaters
{
private int _pageNumber = 1;
public int PageNumber
{
get
{
return _pageNumber;
}
set
{
if (value >= 1)
{
_pageNumber = value;
}
}
}
private int _pageSize = 10;
const int maxPageSize = 50;
public int PageSize
{
get
{
return _pageSize;
}
set
{
if (value >= 1)
{
_pageSize = (value > maxPageSize) ? maxPageSize : value;
}
}
}
}
首先,把函数的返回语句全部comment掉,因为我们将要返回的不在是普通的列表,而是特殊的分页列表类型,PaginationList。接下来,重点来了,我们需要使用一个IQueryable延迟执行的语句来创建分页处理组件PaginationList。所以,IQueryable result 等于 使用复制粘贴return的数据库访问语句代码,_context点Orders点Where。接下来,使用PaginationList的工厂函数来创建分页操作,执行异步操作 await ,Order类型的PaginationList,调用CreateAsync,异步创建创建分页操作的实例。最后直接返回这个实例就可以了。
public async Task<PaginationList<Order>> GetOrdersByUserId(
string userId, int pageSize, int pageNumber)
{
//return await _context.Orders.Where(o => o.UserId == userId).ToListAsync();
IQueryable<Order> result = _context.Orders.Where(o => o.UserId == userId);
return await PaginationList<Order>.CreateAsync(pageNumber, pageSize, result);
}
第三方支付就是一个api请求,对于这个新的api,我们来新建一个控制器来单独处理吧,请同学们右键点击contorleres文件夹,文件名称第三方支付模拟处理器
FakeVanderPaymentProcessController
[ApiController]
[Route("api/[controller]")]
public class FakeVanderPaymentProcessController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> ProcessPayment(
[FromQuery] Guid orderNumber,
[FromQuery] bool returnFault = false
)
{
// 假装在处理
await Task.Delay(3000);
// if returnFault is true, 返回支付失败
if (returnFault)
{
return Ok(new
{
id = Guid.NewGuid(),
created = DateTime.UtcNow,
approved = false,
message = "Reject",
payment_metohd = "信用卡支付",
order_number = orderNumber,
card = new {
card_type = "信用卡",
last_four = "1234"
}
}) ;
}
return Ok(new
{
id = Guid.NewGuid(),
created = DateTime.UtcNow,
approved = true,
message = "Reject",
payment_metohd = "信用卡支付",
order_number = orderNumber,
card = new
{
card_type = "信用卡",
last_four = "1234"
}
});
}
}
在order控制器中完成对这个服务的依赖注入
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ITouristRouteRepository _touristRouteRepository;
private readonly IMapper _mapper;
private readonly IHttpClientFactory _httpClientFactory;
public OrdersController(
IHttpContextAccessor httpContextAccessor,
ITouristRouteRepository touristRouteRepository,
IMapper mapper,
IHttpClientFactory httpClientFactory
)
{
_httpContextAccessor = httpContextAccessor;
_touristRouteRepository = touristRouteRepository;
_mapper = mapper;
_httpClientFactory = httpClientFactory;
}
状态机完成,请同学们回答控制器。如果支付成功,使用订单order调用PaymentApprove函数,订单状态就会改变为支付成功,else{},如果支付失败,那么使用订单order调用PaymentReject,这样订单状态就会改变为失败了。
// 5. 如果第三方支付成功. 完成订单
if (isApproved)
{
order.PaymentApprove();
}
else
{
order.PaymentReject();
}
order.TransactionMetadata = transactionMetadata;
await _touristRouteRepository.SaveAsync();
其实json补丁就是一个json结构的数据,用来表达对目标数据的一些列操作,比如说,假定我们又一条旅游路线1234的数据是这样的
{
"id": "fb6d4f10-79ed-4aff-a915-4ce29dc9c7e1",
"title": "埃及阿斯旺12日跟团游",
"description": "【官方旗舰明星纯玩团】25人封顶|含签证小费全程餐|3晚尼罗河游轮+3晚红海全包度假村+1晚底比斯古都|升级内陆飞机|优质中文导游队伍|七大神庙+赠项目",
"originalPrice": 11999.99,
"discountPercent": 0.1,
"points": null,
"features": null,
"picture": {
"url": "../images/abcdefg.jpg"
}
}
WPF 可创建动态的数据驱动的呈现系统。 系统的每一部分均可通过驱动行为的属性集来创建对象。 数据绑定是系统的基础部分,在每一层中均进行了集成。
传统的应用程序创建一个显示内容,然后绑定到某些数据。 在 WPF 中,控件的所有内容、显示内容的所有方面都是由某种类型的数据绑定生成的。 通过在按钮内部创建复合控件并将其显示内容绑定到按钮的内容属性,会显示按钮中的文本。
public class TouristRouteTitleMustBeDifferentFromDescriptionAttribute: ValidationAttribute
{
protected override ValidationResult IsValid(
object value,
ValidationContext validationContext
)
{
var touristRouteDto = (TouristRouteForCreationDto)validationContext.ObjectInstance;
if (touristRouteDto.Title == touristRouteDto.Description)
{
return new ValidationResult(
"路线名称必须与路线描述不同",
new[] { "TouristRouteForCreationDto" }
);
}
return ValidationResult.Success;
}
}
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传