UWP开发入门——判断设备类型及响应VirtualKey

Cle****-he UID.1073626
2016-07-12 发表

本帖最后由 Clever-he 于 2016-7-12 09:46 编辑

做的工作跟IM软件有关,UWP同时会跑在电脑和手机上。电脑和手机的使用习惯不尽一致,通常我倾向于根据窗口尺寸来进行布局的变化,但是特定的操作习惯是依赖于设备类型,而不是屏幕尺寸的,比如聊天窗口的发送消息。假设如下场景,desktop运行时要求回车键直接发送消息,而mobile版则要求回车键换行,仅能通过点击按钮发送消息。

第一段的铺垫是为了今天提到的两个主题,判断设备类型和处理Shift+Enter的组合。

首先判断设备类型我们使用的是Windows.System.Profile命名空间下的AnalyticsInfo类,通过AnalyticsInfo.VersionInfo.DeviceFamily这个属性我们可以拿到当前的设备类型,小屏幕的设备类型是"Windows.Mobile",其他还是有Windows.Desktop,Windows.Xbox等。这里我们只希望单独区分小屏幕设备,不关心其他设备类型。同时需要指出的是,随之今后Windows设备类型的不断扩充,该属性可能出现的值会不断变化,所以在使用时需要考虑到变化是否会产生bug。

[mw_shl_code=csharp,false]public bool IsAcceptReturn
{
get
{
return AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile";
}
}[/mw_shl_code]

我们根据设备类型来定义了一个属性IsAcceptReturn来标识是否接受回车键换行。

接下来进行Shift+Enter组合键的响应了。UWP在这一点上果然又开了历史倒车,没记错的话连WinForm也无需如此麻烦,竟然要额外地储存一个标志位来标识VirtualKey.Shift是否被按下,在此基础之上再进一步判断是否有Enter键被触发。实际的代码中,我使用了KeyDown事件来记录Shift键的按下,同时通过KeyU事件来进行Enter键触发的判断。

[mw_shl_code=csharp,false]private void KeyUp(KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter)
{
if (_isShiftKeyPressed)
{
int oldIndex = Index;
InputText = InputText.Replace(Environment.NewLine, "\n").Insert(Index, "\n");
Index = oldIndex + 1;
}
else if (IsAcceptReturn == false)
{
SendMessage();
}
}
_isShiftKeyPressed = false;
}

private void KeyDown(KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Shift)
{
_isShiftKeyPressed = true;
}
}[/mw_shl_code]

在KeyUp事件中如果涉及Enter键的触发,将判断_isShiftKeyPressed字段的值,同时根据IsAcceptReturn来判断是否不处理换行,直接发送消息。这里值得一提的是Environment.NewLine在Windows下对应的“\r\n”符号,计算字符串索引时仅作为1位处理,导致我很尴尬总是算不对Shift+Enter换行后的光标位置。无奈出下策将其替换成"\n",其中奥妙各位一试便知。程序对应的XAML如下:

[mw_shl_code=xml,false] <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding Messages}"/>
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding InputText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionStart="{Binding Index, Mode=TwoWay}"
MaxHeight="100" AcceptsReturn="{Binding IsAcceptReturn}" TextWrapping="Wrap">

<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="KeyUp">
<Core:InvokeCommandAction Command="{Binding KeyUpCommand,Mode=OneTime}"/>
</Core:EventTriggerBehavior>
<Core:EventTriggerBehavior EventName="KeyDown">
<Core:InvokeCommandAction Command="{Binding KeyDownCommand,Mode=OneTime}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>

</TextBox>
<Button Grid.Row="1" Grid.Column="1" Width="80" Command="{Binding SendMessageCommand}" Content="Send"/>
</Grid>[/mw_shl_code]

ListView模拟聊天窗口,TextBox的Text属性Binding到了InpuText,同时SlectionStar属性Binding到Index,用于Shift+Enter换行时,插入\n换行符号,及确定光标位置。AcceptsReturn属性在Mobile设备上是true,而在其他设备上就会无视回车键来。TextWrapping属性也很重要,如果不设置为Wrap,即使实际的字符串是包含“\n”等换行符号,但在TextBox中也不会显示出来。

***附件停止解析***

Behaviors的使用计划后续的篇章再介绍,同时本篇的代码使用了Mvvmlight框架,我想是时候把Mvvmlight的介绍也拾起来了!最后是完整代码在GitHub的地址,欢迎看了批评指正哈。

***链接停止解析***

来自:楼上那个蜀黍 开发者交流群:53078485,期待你的加入!

敬告:
为防止不可控的内容风险,本站已关闭新用户注册,新贴的发表及评论;
你现在看到的内容只是互联网用户曾经发表的言论快照,仅用于老用户留存纪念,且仅与科技行业相关,全部内容不代表本站观点及立场;
本站重新开放前已针对包括用户隐私、版权保护、信息安全、国家政策在内的各种互联网法律法规要求,执行了隐患内容的自查、屏蔽和删除;
本站目前所属个人主体,未有任何盈利安排与计划,且与原WFUN.COM所属公司不存在任何关联关系;
如果本帖内容或者相关资源侵犯到您的合法权益,或者您认为存在问题,那么请您务必点此举报或投诉!
本站使用Golang构建,点击此处申请开源鄂ICP备18029942号-4联系站长投诉/举报