前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UWP编程基础

UWP编程基础

作者头像
DearXuan
发布2022-01-19 18:48:31
5070
发布2022-01-19 18:48:31
举报

优势

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

界面布局

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

代码语言:javascript
复制
<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>
DearXuan
DearXuan

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

异步任务与UI线程

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

Thread类

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

代码语言:javascript
复制
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句柄。 命名空间: System.Threading.Tasks 例如,在后台进行登录操作

代码语言:javascript
复制
Task.Run(() => _Login(username, password));

异步方法

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

代码语言:javascript
复制
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线程执行,使用

代码语言:javascript
复制
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Priority, () => { action(); })

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

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

代码语言:javascript
复制
public async static void Invoke(Action action, CoreDispatcherPriority Priority = CoreDispatcherPriority.Normal)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Priority, () => { action(); });
        }

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

示例代码如下

代码语言:javascript
复制
Invoke(() =>
{
    MessageDialog dialog = new MessageDialog("内容")
        {
            Title = "标题"
        };
        dialog.Commands.Add(new UICommand("好的"));
        dialog.DefaultCommandIndex = 0;
        dialog.CancelCommandIndex = 1;
    dialog.ShowAsync();
});

页面与跳转

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

创建JumpTo方法和OnBackClick方法

代码语言:javascript
复制
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()里的代码。之后你就可以使用

代码语言:javascript
复制
JumpTo(typeof(MyPage));

来跳转到指定页面。

画笔

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

纯色画笔

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

代码语言:javascript
复制
private static Color color = new Color() 
{ 
    A = 255, 
    R = 0, 
    G = 255, 
    B = 0 
};

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

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

代码语言:javascript
复制
public static SolidColorBrush brush = new SolidColorBrush(color);

应用画笔

代码语言:javascript
复制
text1.Foreground = brush;

渐变画笔

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

定义LinearGradientBrush与GradientStop

代码语言:javascript
复制
LinearGradientBrush brush = new LinearGradientBrush();
GradientStop gradientStop1 = new GradientStop();
GradientStop gradientStop2 = new GradientStop();

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

DearXuan
DearXuan

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

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

代码语言:javascript
复制
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;

这是效果

DearXuan
DearXuan

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

DearXuan
DearXuan

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

DearXuan
DearXuan

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

DearXuan
DearXuan

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

DearXuan
DearXuan

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

DearXuan
DearXuan

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

MySQL数据库

安装MySql包

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

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

DearXuan
DearXuan

使用命令

代码语言:javascript
复制
Install-Package MySql.Data

来安装MySQL驱动

建立连接

定义连接语句

代码语言:javascript
复制
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";

定义连接,命令,结果集

代码语言:javascript
复制
private static MySqlConnection connection;
private static MySqlCommand command;
private static MySqlDataReader reader;

读取数据

代码语言:javascript
复制
//建立连接
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()来替换值

代码语言:javascript
复制
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();
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021年10月5日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 优势
  • 界面布局
  • 异步任务与UI线程
    • Thread类
      • Task
        • 异步方法
          • 在后台更新UI
            • 页面与跳转
            • 画笔
              • 纯色画笔
                • 渐变画笔
                • MySQL数据库
                  • 安装MySql包
                    • 建立连接
                      • SQL注入防御
                      相关产品与服务
                      云数据库 SQL Server
                      腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档