惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
Security Archives - TechRepublic
Security Archives - TechRepublic
V
Vulnerabilities – Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Proofpoint News Feed
G
GRAHAM CLULEY
P
Privacy International News Feed
The Hacker News
The Hacker News
Forbes - Security
Forbes - Security
U
Unit 42
N
News and Events Feed by Topic
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cisco Blogs
A
About on SuperTechFans
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
I
Intezer
Spread Privacy
Spread Privacy
The Last Watchdog
The Last Watchdog
V2EX - 技术
V2EX - 技术
S
Security @ Cisco Blogs
F
Full Disclosure
S
Secure Thoughts
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
W
WeLiveSecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Project Zero
Project Zero
Recorded Future
Recorded Future
Cyberwarzone
Cyberwarzone
S
Security Affairs
AWS News Blog
AWS News Blog
H
Help Net Security
The GitHub Blog
The GitHub Blog
Hacker News: Ask HN
Hacker News: Ask HN
Vercel News
Vercel News
P
Proofpoint News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Register - Security
The Register - Security
S
Schneier on Security
F
Fortinet All Blogs
C
CERT Recently Published Vulnerability Notes
L
LINUX DO - 最新话题
T
Tor Project blog
T
The Exploit Database - CXSecurity.com
MongoDB | Blog
MongoDB | Blog
Webroot Blog
Webroot Blog

博客园 - AABBbaby

从研发到供应链——轻量级CAD查看器SpinFire Insight在汽车行业的应用价值 DevExpress发布文档MCP Server:提升开发体验的AI文档智能服务(五) 基于嵌入向量的智能检索!HOOPS AI 解锁 CAD 零件相似性搜索新方式 从自研到外购:HOOPS如何帮助工业软件开发商加速上市、聚焦差异化 车企携手Tech Soft 3D:基于 HOOPS 工具集打造Web端一体化工程可视化解决方案 CAD格式转换引擎HOOPS Exchange v2026.2.0:计算镶嵌能力升级,释放3D数据处理新潜力 界面控件DevExpress JS & ASP.NET Core v25.2新版亮点 - AI驱动扩展功能升级 CAD格式转换引擎HOOPS Exchange 2026.2.0发布:率先支持 NX 2512,引领工业数据交换新标杆 界面组件DevExpress正式官宣发布v25.2.5|附高速下载 HOOPS Mesh、HOOPS Access 与 HOOPS Solve 发布 SAM 2.15:全面提升 CAE 数据处理与仿真互操作能力 DevExpress WPF中文教程:Data Grid - 服务器模式和即时反馈模式 界面控件DevExpress WinForms中文教程:Data Grid - 数据绑定(二) CAE后处理开发选商业还是开源工具?HOOPS Envision与VTK/ParaView深度对比 DevExpress发布文档MCP Server:提升开发体验的AI文档智能服务(四) 工业级可视化引擎HOOPS Visualize Web 2026.1.0重塑Web 3D可视化体验 界面控件DevExpress VCL v25.2新功能亮点:支持RAD Studio 13 HOOPS可视化技术如何推动SINTEF Ocean海洋结构仿真软件走向工程化应用? DevExpress WPF中文教程:Data Grid - 示例服务教程 突破性迈进 | HOOPS Exchange 2026.1正式发布DGN阅读器,全面开启 DGN 数据高保真访问时代 3D Web可视化引擎HOOPS Visualize Web v2026.1.0更新发布:持续增强Web端工程级3D可视化能力 应用程序主题研发有妙招!DevExtreme拥有多种预定义主题样式 界面组件DevExpress WPF v22.1 - 全新升级数据分析功能 移动应用开发推荐这个三方组件,时间选择即刻拥有全新体验 UI组件Kendo UI for Angular R3 2022亮点——让应用程序体验更酷炫 如何用界面组件DevExpress WPF创建Excel式的过滤功能?赶紧Get 响应式UI组件DevExtreme 10月新版——v22.1.6全新发布 界面控件DevExtreme中文使用指南——如何构建 & 应用模板 行业领先的界面控价DevExpress 10月新版——v22.1.6发布 「行业应用」界面框架Kendo UI助力企业加速完成财务数据可视化 如何用界面组件DevExpress WinForm创建一个支持High DPI的应用? 界面组件Telerik WinForm R3 2022,让应用启动变得更酷炫 界面组件DevExpress WinForms v22.1新版亮点 - 支持High-DPI UI组件Kendo UI for jQuery R3 2022亮点——拥有全新的按钮组件 界面组件DevExpress WPF TreeView中文指南 - 如何实现数据分层展示 「详解」看界面控件DevExtreme如何实现异步验证 界面控件DevExpress WinForm中文指南 - 使用HTML&CSS模板的条件样式 MyEclipse技术全面解析——Spring IDE,改变应用程序研发 界面组件DevExpress WinForms v22.1 - 类office功能全新升级 界面组件Telerik UI for WPF R3 2022——支持最新的.NET 7预览版 界面控件DevExpress WPF Data Grid组件,拥有XAML设计时项目源向导 B/S端界面控件DevExtreme React Scheduler—与Material UI无缝集成 来看界面组件DevExpress WinForm是如何实现地图搜索的 VCL界面组件DevExpress VCL v22.1 - 发布全新的Shell组件 响应式UI组件集DevExtreme v22.1.5,9月全新发布! 界面组件包DevExpress v22.1.5——9月全新发布 界面控件DevExtreme React Grid—如何将数据导出到Excel文档? 界面控件DevExpress WinForms - 有关.NET Core 6+的项目迁移说明 Visual Studio插件DevExpress CodeRush v22.1- 支持C# 10 一篇文章教你如何用界面组件DevExpress WPF创建一个WPF视图模型 B/S架构下的界面控件DevExtreme甘特图有哪些功能?一起来看 界面控件DevExpress WinForms Property Grid - 全新的Office视图 界面组件DevExpress MAUI & Xamarin v22.1 - 全新的项目模板 界面组件DevExpress WPF Data Grid哪些功能还能增强?一起来看 如何为WPF应用程序制作一个虚拟键盘?这里有答案(Part 1) B/S端界面控件DevExtreme JavaScript—全新的UI模板库 (v22.2) Web开发者福音!创建第一个Vite支持的Web应用(2/2) 界面控件DevExpress WinForms & WPF v22.2——全新的.NET和ARM支持 跨平台UI组件DevExpress XAF v22.1 - 程序集默认面向 .NET 6 如何用界面组件DevExpress WPF Scheduler实现数据的按需加载?
如何为WPF应用程序制作一个虚拟键盘?这里有答案(Part 2)
AABBbaby · 2022-09-08 · via 博客园 - AABBbaby

Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序,同时还能快速构建企业级办公WPF应用程序。UI for WPF支持MVVM、触摸等,创建的应用程序可靠且结构良好,非常容易维护,其直观的API将无缝地集成Visual Studio工具箱中。

在上文中,小编为大家介绍了虚拟键盘的用途、主要的一些功能等(点击这里回顾>>),本文将继续为大家介绍如何为WPF应用程序制作一个虚拟键盘。

主要功能

自定义

你觉得组件的默认外观太标准了?可以使用控件的 VirtualKeayboardTemplateSelector 属性自定义键盘按钮,让键盘与众不同!

<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Telerik.Windows.Themes.Crystal;component/Themes/System.Windows.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Crystal;component/Themes/Telerik.Windows.Controls.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Crystal;component/Themes/Telerik.Windows.Controls.Input.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Crystal;component/Themes/Telerik.Windows.Controls.Navigation.xaml"/>
</ResourceDictionary.MergedDictionaries>

<Style x:Key="KeyButtonStyle" TargetType="telerik:RadButton" BasedOn="{StaticResource RadButtonStyle}">
<Setter Property="Padding" Value="4"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Foreground" Value="#4b6159"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="MinWidth" Value="0"/>
</Style>

<DataTemplate x:Key="RegularKeyTemplate">
<telerik:RadButton Command="{Binding KeyCommand}" AutomationProperties.AutomationId="{Binding DisplayText}" Style="{StaticResource KeyButtonStyle}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ShiftText}" Margin="3 0 0 0" Grid.Row="0" Grid.Column="0" Visibility="{Binding ShowSecondaryText, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding DisplayText}" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</telerik:RadButton>
</DataTemplate>
<DataTemplate x:Key="SpecialKeyTemplate">
<telerik:RadButton Content="{Binding DisplayText}" Command="{Binding KeyCommand}" AutomationProperties.AutomationId="{Binding DisplayText}" Style="{StaticResource KeyButtonStyle}" Background="#ffdac1" MinWidth="40" />
</DataTemplate>
<DataTemplate x:Key="NumpadKeyTemplate">
<telerik:RadButton Content="{Binding DisplayText}" Command="{Binding KeyCommand}" AutomationProperties.AutomationId="{Binding DisplayText}" Style="{StaticResource KeyButtonStyle}"/>
</DataTemplate>
<DataTemplate x:Key="LockKeyTemplate">
<telerik:RadToggleButton Foreground="#4b6159" Content="{Binding DisplayText}" Command="{Binding KeyCommand}" IsChecked="{Binding IsChecked}" Background="#b5ead7"
AutomationProperties.AutomationId="{Binding DisplayText}" Focusable="False" FontSize="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type telerikNavigation:RadVirtualKeyboard}}}"
Padding="0" helpers:ThemeHelper.CornerRadius="30" helpers:ThemeHelper.FocusVisualMargin="0"/>
</DataTemplate>
<telerikNavigation:VirtualKeyboardTemplateSelector x:Key="VirtualKeyboardTemplateSelector"
RegularTemplate="{StaticResource RegularKeyTemplate}"
SpecialTemplate="{StaticResource SpecialKeyTemplate}"
NumpadTemplate="{StaticResource NumpadKeyTemplate}"
LockTemplate="{StaticResource LockKeyTemplate}" />
</ResourceDictionary>

让我们来看看:

界面控件Telerik UI for WPF - 如何为WPF应用制作一个虚拟键盘?

这还不是全部,通过扩展控件的视图模型和可在 VirtualKeyboardTemplateSelector 的 DataTemplates 中使用的其他属性,可以将控件的自定义提升到一个新的水平。您可以将需要实现自定义键的工厂类使用扩展视图模型,现在将演示如何为按钮的背景和前景添加属性。

1. 我们需要创建一个自定义键视图模型来包含背景和前景信息:

public class CustomLockKeyViewModel : LockKeyViewModel
{
public CustomLockKeyViewModel(int virtualKey, double keyWidth, double keyHeight, string displayText)
: base(virtualKey, keyWidth, keyHeight, displayText)
{
}
public Brush Background { get; set; }
public Brush Foreground { get; set; }
}

public class CustomModifierKeyViewModel : ModifierKeyViewModel
{
public CustomModifierKeyViewModel(int virtualKey, double keyWidth, double keyHeight, string displayText)
: base(virtualKey, keyWidth, keyHeight, displayText)
{
}
public Brush Background { get; set; }
public Brush Foreground { get; set; }
}

public class CustomRegularKeyViewModel : RegularKeyViewModel
{
public CustomRegularKeyViewModel(int virtualKey, double keyWidth, double keyHeight, bool showSecondaryText, string displayText = null)
: base(virtualKey, keyWidth, keyHeight, showSecondaryText, displayText)
{
}
public Brush Background { get; set; }
public Brush Foreground { get; set; }
}
public class CustomSpecialKeyViewModel : SpecialKeyViewModel
{
public CustomSpecialKeyViewModel(int virtualKey, double keyWidth, double keyHeight, string displayText)
: base(virtualKey, keyWidth, keyHeight, displayText)
{
}
public Brush Background { get; set; }
public Brush Foreground { get; set; }
}

2. 下一步是创建一个密钥因素:

public class CustomKeyFactory : DefaultKeyFactory
{
private static readonly List<int> specialColorKeyCodes = new List<int>()
{
8, 20, /*CapsLock*/ 9, /*tilde*/ 160,
/*Backspace*/ 226, 162, /*Ctrl*/
91, /*Win*/ 164, /*Alt*/ 165, /*AltGr*/ 93, /*Menu*/
163, /*Ctrl*/ 45, /*Backspace*/ 226, 192
};
public Brush DefaultBrush { get; set; }
public Brush EnterBrush { get; set; }
public Brush SpaceBrush { get; set; }
public Brush SpecialBrush { get; set; }
public Brush ShiftBrush { get; set; }
public Brush DefaultForeground { get; set; }

public CustomKeyFactory()
{
DefaultBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FCFCFC"));
EnterBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F2E50B"));
SpaceBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF7F50"));
SpecialBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#21B20C"));
ShiftBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#17DEEE"));
DefaultForeground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#333333"));
}
public override BaseKeyViewModel CreateKey(int virtualKey, KeyType keyType = KeyType.Normal, string displayText = null, double width = 1, double height = 1, int alternateVirtualKey = -1, string alternateText = null, bool showSecondaryText = false)
{
var keyModel = CreateCustomKey(virtualKey, keyType, displayText, width, height, alternateVirtualKey, alternateText, showSecondaryText);

if (virtualKey == 13) // Enter
{
SetCustomViewModelProperty(keyModel, "Background", EnterBrush);
SetCustomViewModelProperty(keyModel, "Foreground", Brushes.Black);
}
if (virtualKey == 13) // Enter
{
SetCustomViewModelProperty(keyModel, "Background", EnterBrush);
SetCustomViewModelProperty(keyModel, "Foreground", Brushes.Black);
}
else if (virtualKey == 32) // Space
{
SetCustomViewModelProperty(keyModel, "Background", SpaceBrush);
}
else if (virtualKey == 160 || virtualKey == 161) // Shift
{
SetCustomViewModelProperty(keyModel, "Background", ShiftBrush);
}
else if (specialColorKeyCodes.Contains(virtualKey))
{
SetCustomViewModelProperty(keyModel, "Background", SpecialBrush);
SetCustomViewModelProperty(keyModel, "Foreground", Brushes.White);
}
return keyModel;
}

private BaseKeyViewModel CreateCustomKey(int virtualKey, KeyType keyType, string displayText, double width, double height, int alternateVirtualKey, string alternateText, bool showSecondaryText)
{
switch (keyType)
{
case KeyType.Normal:
return new CustomRegularKeyViewModel(virtualKey, width, height, showSecondaryText, displayText) { Background = DefaultBrush, Foreground = DefaultForeground };
case KeyType.Special:
return new CustomSpecialKeyViewModel(virtualKey, width, height, displayText) { Background = DefaultBrush, Foreground = DefaultForeground };
case KeyType.Modifier:
return new CustomLockKeyViewModel(virtualKey, width, height, displayText) { Background = DefaultBrush, Foreground = DefaultForeground };
case KeyType.Lock:
return new CustomLockKeyViewModel(virtualKey, width, height, displayText) { Background = DefaultBrush, Foreground = DefaultForeground };
case KeyType.Numpad:
return new NumpadKeyViewModel(virtualKey, width, height, displayText, alternateVirtualKey, alternateText);
default:
throw new ArgumentException("Unknown key type");
}
}

private static void SetCustomViewModelProperty(BaseKeyViewModel viewModel, string propertyName, object value)
{
var propertyInfo = viewModel.GetType().GetProperty(propertyName);
if (propertyInfo != null)
{
propertyInfo.SetValue(viewModel, value);
}
}
}

3. 现在我们将定义键模板选择器:

<telerik:VirtualKeyboardTemplateSelector x:Key="KeyTemplateSelector">
<telerik:VirtualKeyboardTemplateSelector.RegularTemplate>
<DataTemplate>
<telerik:RadButton Command="{Binding KeyCommand}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Padding="0" Background="{Binding Background}" Foreground="{Binding Foreground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ShiftText}" Margin="3 0 0 0" Visibility="{Binding ShowSecondaryText, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding DisplayText}" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</telerik:RadButton>
</DataTemplate>
</telerik:VirtualKeyboardTemplateSelector.RegularTemplate>
<telerik:VirtualKeyboardTemplateSelector.SpecialTemplate>
<DataTemplate>
<telerik:RadButton Content="{Binding DisplayText}" Command="{Binding KeyCommand}" Padding="0" Background="{Binding Background}" Foreground="{Binding Foreground}"/>
</DataTemplate>
</telerik:VirtualKeyboardTemplateSelector.SpecialTemplate>
<telerik:VirtualKeyboardTemplateSelector.LockTemplate>
<DataTemplate>
<telerik:RadToggleButton Content="{Binding DisplayText}" Command="{Binding KeyCommand}" IsChecked="{Binding IsChecked}" Background="{Binding Background}" Foreground="{Binding Foreground}"/>
</DataTemplate>
</telerik:VirtualKeyboardTemplateSelector.LockTemplate>
</telerik:VirtualKeyboardTemplateSelector>

4. 最后一步是设置自定义密钥因素和模板选择器:

<telerik:RadVirtualKeyboard VirtualKeyboardTemplateSelector="{StaticResource KeyTemplateSelector}" DefaultKeyboardLayout="Compact" Width="675" Height="240">
<telerik:RadVirtualKeyboard.KeyFactory>
<local:CustomKeyFactory />
</telerik:RadVirtualKeyboard.KeyFactory>
</telerik:RadVirtualKeyboard>

界面控件Telerik UI for WPF - 如何为WPF应用制作一个虚拟键盘?


Telerik_KendoUI产品技术交流群:726377843    欢迎一起进群讨论

了解最新Kendo UI最新资讯,请关注Telerik中文网!