UWP编程基础

本文介绍了UWP应用开发的基础,包括XAML布局的使用,避免UI线程阻塞的技巧,Task与async/await的实践,以及MySQL数据库连接与SQL注入防护。跟着教程,初学者将掌握关键概念并提升编程能力。
摘要由CSDN通过智能技术生成

前往我的博客以获得更好的阅读体验UWP编程基础 - DearXuan的主页icon-default.png?t=M3C8https://blog.dearxuan.com/2021/10/05/UWP%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80/

优势

UWP即windows通用平台,用于创建可以运行在所有Windows10以上设备的应用程序。与传统exe应用比起来,UWP应用拥有更严格的权限系统,更美观的操作界面,更强大的自定义控件以及更方便的自适应布局。

界面布局

与Android类似,UWP应用采用XAML作为布局文件

<Page
    x:Class="MailSystem_UWP.View.LoginPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MailSystem_UWP.View"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Height="475" Width="354">

    <Grid Height="325" VerticalAlignment="Center" HorizontalAlignment="Center" Width="288">
        <Grid.RowDefinitions>
            <RowDefinition Height="288*"/>
            <RowDefinition Height="79*"/>
        </Grid.RowDefinitions>
        <TextBlock Margin="10,70,0,0" Text="用户名" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="42" Height="19"/>
        <TextBox x:Name="text1" Margin="10,94,10,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" KeyDown="onKeyDown_1" Height="32"/>
        <TextBlock HorizontalAlignment="Left" Margin="10,156,0,0" Text="密码" TextWrapping="Wrap" VerticalAlignment="Top" Height="19" Width="28"/>
        <PasswordBox x:Name="text2" Margin="10,180,10,0" VerticalAlignment="Top" InputScope="Password" Password="" KeyDown="onKeyDown_2" Height="32"/>
        <Button x:Name="button_login" Content="登录" VerticalAlignment="Bottom" Click="onLoginClick" Margin="0,0,10,10" RenderTransformOrigin="0.131,-0.19" HorizontalAlignment="Right" Height="32" Width="66" Grid.Row="1"/>
        <TextBlock x:Name="label1" HorizontalAlignment="Left" Margin="10,131,0,0" Foreground="Red" Text="请输入用户名" TextWrapping="Wrap" VerticalAlignment="Top" Visibility="Collapsed" Height="19" Width="84"/>
        <TextBlock x:Name="label2" HorizontalAlignment="Left" Margin="10,217,0,0" Foreground="Red" Text="请输入密码" TextWrapping="Wrap" VerticalAlignment="Top" Visibility="Collapsed" Height="19" Width="70"/>
        <TextBlock HorizontalAlignment="Center" Margin="0,10,0,0" Text="登录到MailSystem" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="22" Height="29" Width="177"/>
        <Button x:Name="button_reg" Content="注册" VerticalAlignment="Bottom" Click="onRegClick" Margin="0,0,212,10" RenderTransformOrigin="0.131,-0.19" HorizontalAlignment="Right" Height="32" Width="66" Grid.Row="1"/>
    </Grid>
</Page>

对于初学者,可以使用拖动的方式布局,对于高级开发者,可以前往XAML 概述学习XAML语法,因为许多自定义样式,画笔,布局都是无法通过拖动实现的

异步任务与UI线程

当用户点击一个按钮,系统自动生成一个消息,并插入到UI消息队列中,UI线程处理了这个消息,响应了点击事件。如果在点击事件中进行联网或文件读写等耗时操作,就会导致接下来的消息被阻塞,UI线程无法处理后面的消息,造成界面卡死。

Thread类

使用Thread进行多线程编程,其命名空间为System.Threading。

static void Main(string[] args)
{
    Thread thread = new Thread(cal);
    thread.Start();
}

public static void cal()
{
    Console.Write("123");
    Console.ReadLine();
}

修改thread.IsBackground属性来决定线程运行在前台还是后台,前后台的区别是:当前台线程结束,无论后台线程是否执行完成,都会被强制结束。因此后台线程适合用来监听,而不是保存数据。应用程序的主线程和new Thread()创建的线程默认都是前台线程,如果这些线程都结束,程序随即退出。

Task

使用Task.Run方法在线程池上创建新的后台线程,并返回Task<TResult>句柄。

命名空间: System.Threading.Tasks

例如,在后台进行登录操作

Task.Run(() => _Login(username, password));

异步方法

使用Task可以在后台执行操作,并返回结果,但是当前线程仍然会被Task中的代码阻塞,使用async修饰的异步方法,允许方法中断,并在后台线程结束后从中断处继续执行。

private async void onLoginClick(object sender, RoutedEventArgs e)
{
    //获取用户名和密码,以便异步调用
    string username = text1.Text;
    string password = text2.Password;
    //按钮不可用
    SetAvailable(false);
    //异步执行检查代码,防止UI线程卡死
    await Task.Run(() => _Login(username, password));
    //按钮可用
    SetAvailable(true);
}

 在检测登录信息前,将按钮设置为不可用状态,使用await修饰的Task语句,将检测登录信息的函数放在后台执行,并中断当前代码,当_Login方法结束时,程序从中断处继续执行,将按钮设置为可用。

使用该方法不会阻塞onLoginClick()所在的线程,因此不会造成界面卡死。

在后台更新UI

为了在后台线程中更新UI,需要将代码切换至UI线程执行,使用

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Priority, () => { action(); })

方法将action()插入UI消息队列中,并由UI线程执行。值得注意的是,一旦lambda表达式里的代码开始执行,该函数就会立即返回,因此不应该在lambda表达式中进行需要等待的操作,例如请求用户输入。

为了方便调用,我已经写好了Invoke()方法,你可以直接复制下面的代码

public async static void Invoke(Action action, CoreDispatcherPriority Priority = CoreDispatcherPriority.Normal)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Priority, () => { action(); });
        }

Invoke()方法接收一个函数,并在UI线程执行。

示例代码如下

Invoke(() =>
{
    MessageDialog dialog = new MessageDialog("内容")
        {
            Title = "标题"
        };
        dialog.Commands.Add(new UICommand("好的"));
        dialog.DefaultCommandIndex = 0;
        dialog.CancelCommandIndex = 1;
    dialog.ShowAsync();
});

页面与跳转

右键解决方案-添加-新建项,选择空白页,即可新建页面。

创建JumpTo方法和OnBackClick方法

public static void JumpTo(Type page)
{
    Frame root = Window.Current.Content as Frame;
    Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += OnBackClick;
    SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = root.CanGoBack ? AppViewBackButtonVisibility.Visible : Windows.UI.Core.AppViewBackButtonVisibility.Collapsed;
    root.Navigated += OnNavigated;
    root.Navigate(page);
}
private static void OnBackClick(object sender, BackRequestedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
        return;
    if (rootFrame.CanGoBack && e.Handled == false)
    {
        e.Handled = true;
        rootFrame.GoBack();
    }
}

JumpTo()方法用于跳转至指定页面,并在左上角创建返回按钮,点击返回按钮后执行OnBackClick()里的代码。之后你就可以使用

JumpTo(typeof(MyPage));

来跳转到指定页面。

画笔

使用自定义画笔可以修改控件的样式,例如边框颜色。

纯色画笔

纯色画笔可以指定绘制某一种颜色。先定义颜色color为绿色

private static Color color = new Color() 
{ 
    A = 255, 
    R = 0, 
    G = 255, 
    B = 0 
};

注意Color的命名空间是Windows.UI,而不是System.Drawing。

定义纯色画笔,并使用color初始化

public static SolidColorBrush brush = new SolidColorBrush(color);

应用画笔

text1.Foreground = brush;

渐变画笔

渐变画笔用于绘制包含渐变颜色的界面

定义LinearGradientBrush与GradientStop

LinearGradientBrush brush = new LinearGradientBrush();
GradientStop gradientStop1 = new GradientStop();
GradientStop gradientStop2 = new GradientStop();

LinearGradientBrush即为渐变画笔,以下图为例

对角线方向线性渐变的渐变轴

渐变方向为(0,0)到(1,1),即起点和终点,那么向量(1,1)即是渐变向量。为了描述该向量,需要定义向量的起点与终点,并在向量上的不同地方定义不同的颜色。定义颜色需要用到GradientStop,我们称GradientStop为梯度点

现在初始化梯度点,并修改背景画笔

gradientStop1.Color = new Windows.UI.Color() { A = 255, R = 255, G = 0, B = 0 };
gradientStop1.Offset = 0;
gradientStop2.Color = new Windows.UI.Color() { A = 255, R = 0, G = 0, B = 255 };
gradientStop2.Offset = 1;
brush.GradientStops.Add(gradientStop1);
brush.GradientStops.Add(gradientStop2);
brush.StartPoint = new Point(0, 0);
brush.EndPoint = new Point(1, 0);
grid.Background = brush;

这是效果

 Color是梯度点的颜色,Offset规定了梯度点在整个渐变向量中的位置,范围为0~1。如果你输入0.5,那么画笔的前50%是渐变图案,后50%是纯色,就像下面这张图

 如果你输入2,那么画笔就会有一半画到窗体外面,也就是说只有前50%的画笔有效,比如下面这张图,你看不到蓝色,因为蓝色被画到外面了 

 StartPoint和EndPoint分别是画笔相对于绘制区域的起点和终点坐标,即是渐变向量。x,y轴的正方向分别是向右和向下,(0,0)~(1,1)是默认区域,这是斜向下的渐变。

 为了实现垂直方向的渐变,需要定义向量(0,1),因此StartPoint为(0,0),EndPoint为(0,1)

起始点和终点也可以小于1,如果它们分别为(0,0),(0.5,0.5),这说明画笔只对整个Page的左上角有效。如下图

 左下方和右上角颜色不是纯色,这是因为之前的渐变向量填充了这里的颜色,而右下角不受渐变向量的控制,因此是纯蓝色

MySQL数据库

安装MySql包

 在VS的下方打开“程序包管理器控制台”

如果没有则转到“视图”->“其他窗口”->“程序包管理器控制台”,第一次打开需要初始化,一般在5秒左右

使用命令

Install-Package MySql.Data

 安装MySQL驱动

建立连接 

定义连接语句

private const string DATABASE_SERVER = "localhost";
private const string DATABASE_NAME = "dearxuan";
private const string DATABASE_USER = "root";
private const string DATABASE_PASSWORD = "root";
private const string DATABASE_PORT = "3306";
private const string SQL_CONNECTION_STR = 
    "server=" + DATABASE_SERVER + 
    ";user=" + DATABASE_USER + 
    ";database=" + DATABASE_NAME + 
    ";port=" + DATABASE_PORT + 
    ";password=" + DATABASE_PASSWORD + 
    ";SslMode=None";

定义连接,命令,结果集

private static MySqlConnection connection;
private static MySqlCommand command;
private static MySqlDataReader reader;

读取数据

//建立连接
connection = new MySqlConnection(SQL_CONNECTION_STR);
connection.Open();

//执行语句
command = new MySqlCommand(“SELECT * FROM dearxuan”, connection);

//获取结果集
reader = command.ExecuteReader();
while (reader.read())
{
    //读取第一项和第二项
    string username = reader[0].ToString();
    string password = reader[1].ToString();
}

SQL注入防御

使用预编译的方法来预防SQL注入攻击。预编译语句不包含数据的值,并且会在填入值之前进行语法分析,之后填入的值即使包含了SQL关键字也仍然会被当成字符串处理

在SQL语句中以"@"开头的字符串代替原本值的位置,并使用AddWithValue()来替换值

string sql = "SELECT * FROM dearxuan WHERE username=@username AND password=@password"
command = new MySqlCommand(sql, connection);
command.Parameters.AddWithValue("username", username);
command.Parameters.AddWithValue("password", password);
reader = command.ExecuteReader();

Contents 开发桌面应用 设置开发环境 系统要求 安装开发人员工具 启用设备进行开发 开发人员模式功能和调试 创建一个开发者帐户 入门 概述 适用于 Windows 应用的 Visual Studio 模板 生成适用于 Windows 11 的应用 让你的应用在 Windows 11 上出色表现 设计和 UI 概述 Windows 11 中的设计 Windows 11 设计原则 Windows 11 签名体验 Geometry 颜色 分层和提升 材料 图标 版式 设计基础知识 概述 应用设计简介 导航基础知识 概述 实现基本导航 导航历史记录和向后导航 命令基础知识 内容基础知识 教程 创建用户界面 创建自适应布局 设置控件的样式 布局 概述 页面布局 屏幕大小和断点 响应式设计技术 使用 XAML 的布局 显示多个视图 显示多个视图 使用 AppWindow 使用 ApplicationView 对齐、边距和填充 面板 概述 教程:使用布局面板 拆分视图 自定义面板 自定义面板示例:BoxPanel 附加的布局 转换 概述 3D 透视效果 Z 深度和阴影 控制 概述 控件和事件简介 命令处理简介 基本输入 按钮 复选框 组合框和列表框 超链接 单选按钮 评分控件 滑块 切换开关 集合 概述 列表视图和网格视图 翻转视图 PipsPager 树视图 ItemsRepeater 项目容器和模板 项目容器和模板 数据模板选择 列表视图项模板 网格视图项模板 选择和交互 集合命令处理 “选择模式”概述 轻扫 下拉刷新 筛选集合 其他集合选项和自定义 反转列表 嵌套 UI 对话框和浮出控件 概述 对话框 浮出控件 教学提示 窗体 媒体、图形和形状 动画图标 图像和图像画笔 墨迹 媒体播放 自定义传输控件 形状 Web 视图 菜单和工具栏 菜单和上下文菜单 命令栏 命令栏浮出控件 菜单浮出控件和菜单栏 导航 痕迹导航栏 列表/详细信息 导航视图 Pivot 选项卡视图 人员 联系人卡片 头像图片 选取器 颜色选取器 日期和时间控件 日历日期选取器 日历视图 日期选取器 时间选取器 滚动和布局 Expander 滚动和平移控件 语义式缩放 双窗格视图 状态和信息 进度 工具提示 信息栏 文本 概述 自动建议框 文本块 RTF 块 文本框 富编辑框 密码框 数字框 标签 内容链接 手写视图 样式 概述 颜色 版式 图标 概述 应用图标和徽标 Segoe MDL2 图标 亚克力 Mica 显示焦点 声音 写入样式 XAML 画笔 XAML 样式 XAML 控件模板 ResourceDictionary 和 XAML 资源引用 XAML 主题资源 间距 角半径 移动 概述 计时和缓动 方向性和引力 运动练习 页面过渡 连贯的动画 视差 XAML 中的动画 属性动画 情节提要动画 关键帧以及缓动函数动画 Shell Toast 通知 UX 指南 发送本地 Toast C# 应用 C++ UWP 应用 C++ WRL 应用 其他应用 Toast 内容 Content 架构 计划 toast 其他功能 自定义音频 进度条 挂起更新 自定义时间戳 集合 标头 通知侦听器 已过时 锁屏提醒通知 推送通知 概述 WNS 优先级 将 WNS 流量加入允许列表 由推送通知向导生成的代码 任务栏 将应用固定到任务栏 标题栏 动态磁贴 辅助磁贴 指南 固定到“开始”屏幕 固定到任务栏 桌面应用程序 磁贴内容 磁贴内容架构 特殊磁贴模板 发送本地磁贴通知 可追踪的磁贴通知 主要磁贴 API 磁贴和 Toast 通知的语言、比例和高对比度支持 杂项 通知可视化工具 通知传递方法 通知通道类型 使用 Webpush 和 VAPID 的备用通道 定期通知 输入和交互 概述 输入基础版 指针输入 凝视 笔和 Windows Ink 教程:向应用添加墨迹支持 识别笔划墨迹 存储和检索笔划墨迹 添加 InkToolbar 触摸 鼠标 Keyboard 访问键 键盘加速键 键盘事件 适用于键盘、手柄、遥控器和辅助功能工具的焦点导航 编程焦点导航 响应触摸键盘的存在 使用输入范围更改触摸键盘 文本输入 自定义文本输入 文本缩放 选择文本和图像 输入法编辑器 输入法编辑器要求 ......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dear_Xuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值