0. 写在前面
因为马上就要考试了,所以写一个博客对知识点进行总结。
还有一点在于,自己写 Java 后端也有一定的时间了,已经对 Java 语言的局限性已经有所体会,所以想着尝试用其他的语言进行后端开发。
可能之后会尝试去了解 C#/Go 吧。
1. 文件结构
我们首先会创建了一个解决方案,一个解决方案里面可能有很多项目(加粗的项目作为启动项目,只有启动项目启动之后剩余的项目才能进行加载)。默认的解决方案中,我们只有一个项目;
在 Properties 中,保存我们相关项目的信息;
引用中包含我们调用的各种库;
App.xaml/App.xaml.cs 表示应用程序的最先加载的程序;
MainPage.xaml UWP 默认加载的主页面。
每一个界面中都会有一个 InitializeComponent 方法,在这个方法的源代码中,会有对 xaml 中各种控件(control)的加载,这样就能在启动之后显示我们的所设置的布局。
2. 生命周期
应用程序的生命周期是指从应用程序部署到计算机上到应用程序从计算机中删除 的整个阶段。
当启动或激活应用时,这些应用会进入在后台运行状态。 如果应用由于前台应用启动而需要移动到前台,则该应用将获取 LeavingBackground 事件。
由于预启动,应用的 OnLaunched () 方法可能由系统启动,而不是由用户启动。 由于应用在后台预启动,因此可能需要在 OnLaunched() 中采取不同操作。
当用户最小化某个应用时,Windows 会等待数秒,以查看用户是否会切换回该应用。 如果用户在此时间范围内未切换回,并且任何扩展执行、后台任务或活动赞助执行都未处于活动状态,则 Windows 将暂停该应用。 只要应用中不存在任何处于活动状态的扩展执行会话等,该应用也将在出现锁屏界面时暂停 。
2.1 app data/session data
app data 是和应用程序相关的内容,在应用程序的整个生命周期中都存在的。
当我们需要保存应用程序的某些数据以便下一次访问时依然可以 使用时,我们可以将数据保存成应用程序数据(即 app data),也可以将数据写到 文件中。
Windows.Storage.ApplicationDataContainer localSettings =
Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values["Name"] = TextBox1.Text;
//将我们的数据暂存到 localSetting 中,可以理解为一个缓存
3. 基本控件
3.1 选择控件
RadioButton 单选按钮,在多个选项中可以使用 GroupName 进行分组;
<StackPanel> <RadioButton Content="好" GroupName="comment"/> <RadioButton Content="一般" GroupName="comment"/> <RadioButton Content="差" GroupName="comment"/> </StackPanel>
ComboBox 下拉框,可以在下拉框中添加各种奇怪的控件(bushi);
<ComboBox Header="show something to me" FontSize="32" PlaceholderText="take a ability" PlaceholderForeground="Gray"> <x:String>Blue</x:String> <x:String>Green</x:String> <x:String>Red</x:String> <x:String>Yellow</x:String> <TextBlock Text="this is just a test"/> <!--这种控件添加到 ComboBox 也是被允许的--> </ComboBox>
CheckBox 复选框,提供多选功能。可以有三种状态,表示未选中、未全选、完全选中;
<CheckBox Content="hello" FontSize="32" IsThreeState="True" IsChecked="{x:Null}"/> <!--对应代码为 false, x:null, true-->
Button 最常用的按钮控件(在这里提醒一点,基本所有控件的大小默认都是根据字体大小,即 FontSize 自动调整的,默认的属性为 Auto)。除了在按钮中使用默认的 Content 属性,还可以使用 Image、TextBlock 控件包裹在里面;
<Button Content="Standard XAML button" Click="Button_Click" /> <Button Content="Button" Click="Button_Click" AutomationProperties.Name="Pie"> <Image Source="/Assets/Slices.png" AutomationProperties.Name="Slice"/> </Button> <StackPanel> <TextBlock Text="The following buttons' content may get clipped if we don't pay careful attention to their layout containers." Margin="0,0,0,8" TextWrapping="Wrap"/> <TextBlock Text="One option to mitigate clipped content is to place Buttons underneath each other, allowing for more space to grow horizontally:" Margin="0,0,0,8" TextWrapping="Wrap"/> <Button HorizontalAlignment="Stretch" Margin="0,0,0,5"> This is some text that is too long and will get cut off </Button> <Button HorizontalAlignment="Stretch"> This is another text that would result in being cut off </Button> <TextBlock Text="Another option is to explicitly wrap the Button's content" Margin="0,8,0,8"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button MaxWidth="240" Margin="0,0,8,0"> <TextBlock Text="This is some text that is too long and will get cut off" TextWrapping="WrapWholeWords"/> </Button> <Button MaxWidth="240"> <TextBlock Text="This is another text that would result in being cut off" TextWrapping="WrapWholeWords"/> </Button> </StackPanel> </StackPanel>
HyperlinkButton 表示超链接跳转;
<HyperlinkButton Content="Microsoft home page" NavigateUri="http://www.microsoft.com"/>
RepeatButton 提供一个可以按住之后,连续触发的按钮;
<RepeatButton Content="Click and hold" Click="RepeatButton_Click"/>
ToggleButon 看起来像一个Button,但工作起来像一个CheckBox。它通常有两种状态,但是跟 CheckBox 一样,也是存在三种状态的情况(虽然第三种状态并不是很能看得出来);
<ToggleButton Content="ToggleButton" Click="Button_Click"/>
ToggleSwitch 这就表示一个开关,拥有两种状态,可以设置它开启或者关闭时显示的不同内容。
<StackPanel Orientation="Horizontal"> <ToggleSwitch OnContent="开启啦" OffContent="关闭咯" FontSize="32" x:Name="state" IsOn="True"/> <ProgressRing IsActive="{Binding ElementName=state, Path=IsOn, Mode=OneWay}" Width="40"/> <!--使用了一个最基本的绑定,之后会提--> </StackPanel>
3.2 进度控件
Slider 进度条控件,是表示连续区间数值的控件;
<Slider Width="200" Minimum="500" Maximum="1000" StepFrequency="10" SmallChange="10" LargeChange="100" Value="800" /> <!--设置进度条最大值、最小值、每次跳转的步数、当前数值以及最大最小变化量--> <Slider AutomationProperties.Name="Slider with ticks" TickFrequency="10" TickPlacement="Outside" /> <!--可以设置平均刻度,以及刻度的位置-->
ProcessRing 加载进度条。
<muxc:ProgressRing IsActive="True" /> <ProgressRing Width="60" Height="60" Value="0" IsIndeterminate="False"/> <!--IsIndeterminate 表示进度条是否是不确定的,默认是 true-->
3.3 文本控件
TextBlock 只读文本显示控件,可以使用内联的元素进行各种精确的设定;
<TextBlock Text="I am a TextBlock"/> <Page.Resources> <Style TargetType="TextBlock" x:Key="CustomTextBlockStyle"> <Setter Property="FontFamily" Value="Comic Sans MS"/> <Setter Property="FontStyle" Value="Italic"/> </Style> <Page.Resources> <!--设定基本的 TextBlock 样式--> <TextBlock Text="I am a styled TextBlock" Style="{StaticResource CustomTextBlockStyle}"/> <TextBlock> <Run FontFamily="Times New Roman" Foreground="DarkGray"> Text in a TextBlock doesn't have to be a simple string.</Run> <LineBreak/><!--进行换行--> <Span>Text can be <Bold>bold</Bold>, <Italic>italic</Italic>, or <Underline>underlined</Underline>. </Span> </TextBlock>
TextBox TextBox 相当于可编辑的 TextBlock(当然,我们可以使用 IsReadOnly 让它不可编辑);
<TextBox AutomationProperties.Name="simple TextBox"/> <TextBox Text="I am super excited to be here!" AutomationProperties.Name="customized TextBox" IsReadOnly="True" FontFamily="Arial" FontSize="24" FontStyle="Italic" CharacterSpacing="200" Foreground="CornflowerBlue" />
RichTextBlock 富文本控件,使用 Paragraph 进行分段。如果需要在其中加入控件,需要使用 InlineUIContainer。
<RichTextBlock> <Paragraph> <InlineUIContainer> <Image Source="https://hexoblogimages-1304994718.cos.ap-nanjing.myqcloud.com/202112211555684.jpg" Stretch="Uniform" Width="500" Height="600"/> </InlineUIContainer> </Paragraph> <Paragraph> <x:String>hello World</x:String> <InlineUIContainer> <TextBlock Text="这只是一个测试,咕咕咕"/> </InlineUIContainer> </Paragraph> </RichTextBlock>
3.4 媒体控件
image 显示图片的控件。image 控件的伸缩有四种情况:
- None 按照正常图片大小进行填充;
- Fill 忽视原图的横纵比,将图片缩放到规定的大小;
- Uniform 保持图片的横纵比,将图片尽可能地缩放到规定地大小,如果超出则留空;
- UniformToFill 保持图片地横纵比,将图片通过横纵比进行放大,如果过大,会有超出的部分。
<InlineUIContainer> <Image Source="https://hexoblogimages-1304994718.cos.ap-nanjing.myqcloud.com/202112211555684.jpg" Stretch="Uniform" Width="500" Height="600"/> </InlineUIContainer>
MediaPlayerElement 媒体播放器,播放视频或者展示图片;
<MediaPlayerElement Source="/Assets/SampleMedia/ladybug.wmv" MaxWidth="400" AutoPlay="False" AreTransportControlsEnabled="True" /> <!--AreTransportControlsEnabled 是自带的播放控件-->
WebView 显示对应的网络链接内容。
<WebView Source="https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/web-view" />
3.5 物件集合
FlipView 可以将多个图片“打包”成一个整体,拥有自带的前后切换框;
<FlipView MaxWidth="400" Height="270"> <Image Source="ms-appx:///Assets/SampleMedia/cliff.jpg" AutomationProperties.Name="Cliff"/> <Image Source="ms-appx:///Assets/SampleMedia/grapes.jpg" AutomationProperties.Name="Grapes"/> <Image Source="ms-appx:///Assets/SampleMedia/rainier.jpg" AutomationProperties.Name="Rainier"/> <Image Source="ms-appx:///Assets/SampleMedia/sunset.jpg" AutomationProperties.Name="Sunset"/> <Image Source="ms-appx:///Assets/SampleMedia/valley.jpg" AutomationProperties.Name="Valley"/> </FlipView>
GridView 可以自动排列行和列,如果图片显示超出范围,会进行自动排版;
ListView/ListBox ListBox 算是 ListView 的简化版本,可以使用 SelectIndex 和 SelectItem 获取对应选取的元素。
<ListBox ItemsSource="{x:Bind Fonts}" DisplayMemberPath="Item1" SelectedValuePath="Item2" Height="164" Loaded="ListBox2_Loaded"/>
4. 布局
Grid 网格布局,可以类比为 Excel 的行和列,在 Grid.RowDefinitions 和 Grid.ColumnDefinitons 中进行定义:
- 默认是
*
,表示布局的占比; - 可以设置数据,表示正常的像素;
- 设置 Auto,宽度/高度会根据控件的大小进行调整。
Grid 可以使用 RowSpan/ColumnSpan 进行“单元格合并”。
<Grid Width="240" Height="120" Background="Gray"> <Grid.ColumnDefinitions> <ColumnDefinition Width="50" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Rectangle Fill="Red" Grid.Column="0" Grid.Row="0" /> <Rectangle Fill="Blue" Grid.Row="1" /> <Rectangle Fill="Green" Grid.Column="1" /> <Rectangle Fill="Yellow" Grid.Row="1" Grid.Column="1" /> </Grid>
- 默认是
StackPanel 将各种物件整合成一行的布局,也是最基本的布局;
<StackPanel Orientation="Vertical"> <Rectangle Fill="Red"/> <Rectangle Fill="Blue"/> <Rectangle Fill="Green"/> <Rectangle Fill="Yellow"/> </StackPanel>
ViewBox 限制这个布局中的内容放大或是缩小;
<Viewbox Height="300" Width="300" Stretch="Uniform" StretchDirection="UpOnly"> <Border BorderBrush="Gray" BorderThickness="15"> <StackPanel Background="DarkGray"> <StackPanel Orientation="Horizontal"> <Rectangle Fill="Blue" Height="10" Width="40"/> <Rectangle Fill="Green" Height="10" Width="40"/> <Rectangle Fill="Red" Height="10" Width="40"/> <Rectangle Fill="Yellow" Height="10" Width="40"/> </StackPanel> <Image Source="ms-appx:///Assets/Slices.png"/> <TextBlock Text="This is text." HorizontalAlignment="Center"/> </StackPanel> </Border> </Viewbox>
Canvas 绝对布局控件,可以使用 Canvas.left 等等进行绝对方位的布局。Canvas 还有一个 Z 轴,表示深度。
<Canvas Width="120" Height="120" Background="Gray"> <Rectangle Fill="Red" Canvas.Left="0" Canvas.Top="0" Canvas.ZIndex="0" /> <Rectangle Fill="Blue" Canvas.Left="20" Canvas.Top="20" Canvas.ZIndex="1" /> <Rectangle Fill="Green" Canvas.Left="40" Canvas.Top="40" Canvas.ZIndex="2" /> <Rectangle Fill="Yellow" Canvas.Left="60" Canvas.Top="60" Canvas.ZIndex="3" /> </Canvas>
5. 事件触发
5.1 添加控件
XAML 在设计阶段中添加控件,即就是在 xaml 中写下控件代码;
C# 在运行中添加各种控件。
Button button = new Button(); button.Content = "mission complete"; grid.Children.Add(button);
5.2 事件绑定
事件绑定的函数基本模板 ____(object sender, RoutedEventArgs e)
:
XAML 直接在控件中写,
Click="button_name_Click"
;C# 在初始页面加载时进行绑定
button_name.Click += button_name_Click;
。这里使用 += 的原因在于,对于这个控件,我们进行事件的绑定是一个委托类型。我们正常来说是应该叠加上去,而不是单纯的用 = 把原有的事件替代掉。
5.3 页面跳转
Frame.Navigate(typeof(Page1)) Page1 是要跳转的页面,根据要跳转的页面进行修改 ;
Frame.Navigate(typeof(Page1), obj); obj 是要传递的参数,可以变化的;
Frame.GoBack()/Frame.GoForward() 向后/向前;
Frame.CanGoBack/Frame.CanGoForward 是否能够向后/向前。
5.4 数据绑定
对一些控件值,我们除了硬编码或者通过事件的触发进行更改,我们还可能让其根据某个值进行更改
- oneWay 在数据源更改之后,对绑定数据进行变更;
- oneTime 只有在初始化的时候才会进行变更;
- TwoWay 绑定值的更改同样会作用于数据源。
<Slider Width="800" HorizontalAlignment="Center" VerticalAlignment="Center"
x:Name="slider_value" Maximum="400" Value="50"
TickFrequency="10" TickPlacement="Inline">
<Slider.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="Height" FontSize="40"/>
<TextBlock Text="全体目光向我看齐,嘉然是我爹" FontSize="40"/>
</StackPanel>
</DataTemplate>
</Slider.HeaderTemplate>
</Slider>
<TextBox Width="400" Grid.Row="1" HorizontalAlignment="Center"
Height="Auto" FontSize="50"
VerticalAlignment="Center" x:Name="textBox_value"
Text="{Binding ElementName=slider_value, Path=Value, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
<!--因为默认是失去焦点之后才会进行更改,这里改成 PropertyChanged-->
5.5 数据模板/样式
data template/style:
- Inline 内嵌在某一个控件内部;
- Page resource 定义在页面的 xaml 代码中,紧跟
在元素的里面 ; - App resource 定义在 app.xaml 代码中,紧跟在
元素的里面 ; - Resource dictionary 定义在单独的文件中,在
里面。
x:Name=”” 控件的命名 x:Key=”” 资源的名称。
在 Style 中,可以使用 BaseOn 继承之前写的数据样式,可以直接在内部进行重写。
<Page.Resources>
<DataTemplate x:Key="ViewNotesDataTemplate">
<Grid>
<TextBlock x:Name="txtNoteTitle" Text="{Binding Title}" FontSize="24" ></TextBlock>
</Grid>
</DataTemplate>
</Page.Resources>
<ListBox x:Name="lstBoxNotes" ScrollViewer.HorizontalScrollMode="Auto"
ScrollViewer.VerticalScrollMode="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Margin="279,97,278,97" Width="809"
ItemTemplate="{StaticResource ViewNotesDataTemplate}"/>
<!--DataTemplate 使用样例。使用 ScrollViewer 显示下拉框-->
5.6 弹出窗体
注意,MessageDialog、PopupMenu 是在 Windows.UI.Popups 这个包中。
ToolTip 表示一个弹出的消息提示框;
ToolTip tool = new ToolTip(); tool.Content = "click to start"; ToolTipService.SetToolTip(tool, button_name);
PopupMenu 本质是一个菜单栏,可以类比于 Windows 中的右键菜单。
Windows.Ui.Popups.PopupMenu pMenu = new Windows.Ui.Popups.PopupMenu(); UICommand redCommand = new UICommand(); redCommand.Label = "Red"; redCommand.Id = 1; pMenu.Command.Add(redCommand); var chosenCommand = await pMenu.ShowForSelectionAsync( new Rect(e.GetPosition(null)), e.GetPosition(null)); //因为这里的操作是耗时的,所以我们需要使用异步(async) //await 就像服务员点餐给你菜单一样,程序在这里会进行等待;等待结束就像是告诉服务员餐点好了,程序就继续进行了
6. 文件存储
每一个通用应用程序默认只有权限访问三个路径(app 安装目录、app data 目录、下载目录),其他的路径如果要访 问的话有两种办法:
(1)在 manifest 文件中声明能力,即增加权限;
(2)使用 FilePicker。
其中第一种办法适用于常见的知名文件夹,如文档库、视频库、音乐库等,第二种方法适用于所有的文件夹。
6.1 使用 FilePicker
通过使用 FilePicker 来增加文件读取写入的范围;
FileOpenPicker openPicker = new FileOpenPicker()
{
CommitButtonText = "Open this!",
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.Downloads
};
openPicker.FileTypeFilter.Add(".txt");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
try
{
await new MessageDialog(await FileIO.ReadTextAsync(file)).ShowAsync();
}
catch (Exception ex)
{
await new MessageDialog(ex.ToString()).ShowAsync();
}
}
FileSavePicker savePicker = new FileSavePicker()
{
CommitButtonText = "Save Here!",
SuggestedFileName = "cxy可爱捏",
};
savePicker.FileTypeChoices.Add("the format we can read",
new[] { ".txt", ".md" });
StorageFile store = await savePicker.PickSaveFileAsync();
if (store != null)
{
try
{
await FileIO.WriteTextAsync(store, "114514");
}
catch (Exception ex)
{
await new MessageDialog(ex.ToString()).ShowAsync();
}
}