CPF C#跨平台桌面UI框架
系列教程
CPF 入门教程 - 各个控件介绍(八)
大部分控件和WPF对应的,用法大部分可以参考WPF
注意线程安全问题,大部分控件的依赖属性是可以支持线程访问的,但是如果是集合类型的,对集合添加移除这些操作会有线程安全问题,必须委托到主线程。控件的方法不支持线程调用,必须委托到主线程。
对于MainModel 也必须注意,最好不要多线程访问MainModel的属性,必须委托到主线程。
控件的Invoke方法或者CPF.Threading.Dispatcher.MainThread.Invoke
Invoke(()=> { //操作代码 });
Border
在另一个元素四周绘制边框和背景,支持任意圆角和阴影,大部分元素都提供边框设置
CornerRadius属性设置四个角的圆角大小
BorderType定义两种边框模式
/// 四周边框一样粗,BorderStroke属性定义粗细样式,支持设置虚线
BorderStroke,
/// 四周边框可以不同粗细,BorderThickness属性定义四周粗细,如果定义圆角了可能会有锯齿
BorderThickness,
ShadowHorizontal ,ShadowVertical,ShadowBlur,ShadowColor 提供对阴影的设置
Button
继承自ContentControl
Content属性可以设置字符串,图片或者UIElement等等的内容,一般的如果做图标加文字效果,直接在设计器里加图标加文字的控件组就行
CheckBox
Content属性可以设置字符串,图片或者UIElement等等的内容
IsThreeState定义是否是三种状态。 IsChecked定义选中状态
RadioButton
Content属性可以设置字符串,图片或者UIElement等等的内容
通过这个GroupName属性分组,通过Window或者View这类的根元素的GetRadioButtonValue()方法获取选中值,或者用RadioButtonGroup自动绑定
[RadioButtonGroup("分组1", true)]//绑定RadioButton分组的值,只能在View里使用,默认是用RadioButton的Content作为绑定值 public string Group1 { get { return GetValue<string>(); } set { SetValue(value); } }
ComboBox
Items可以绑定数组或者集合,比如combobox.Items=new String[]{“dfsf”,”gdfs”};
除了直接设置之外也可以直接调用Add方法添加,ComboBox.Items.Add(“dfsfs”);
也可以直接添加ListBoxItem对象
数据项可以是简单的字符串,数值,也可以是自定义类,如果是自定义类,需要定义 DisplayMemberPath和SelectedValuePath 属性确定该显示自定义对象的哪个属性。
IsVirtualizing虚拟模式,如果用虚拟模式,Item的高度只能是固定的那种,下拉框高度也是固定的,这种模式可以加载大量数据不会卡
IsEditable 启用编辑模式
SelectionMode 选择模式,可以设置为多选或者单选
ItemTemplate 设置Item的模板,类型继承ListBoxItem
ListBox
数据绑定与操作和ComboBox基本一致,
ItemsPanel 定义内部布局容器,你可以改成水平的或者WrapPanel等等,比如 ItemsPanel=new StackPanel{Orientation=Orientation.Horizontal},虚拟模式下只能用StackPanel
TreeView
Items里加数据外,可以直接加TreeViewItem
DisplayMemberPath定义自定义对象显示的属性
ItemsMemberPath 定义自定义对象子节点的属性名
ItemTemplate 定义模板类型继承TreeViewItem
DataGrid
暂时不支持自适应列宽度
Columns定义列,列宽支持固定值和权重,权重就是对固定宽度之后的剩余空间的分配,DataGridComboBoxColumn的BindingMode定义绑定模式,双向绑定和自动刷新需要数据源支持集合通知INotifyCollectionChanged和里面的数据项要实现INotifyPropertyChanged接口
new DataGrid { Width = "60%", Height = "60%", Columns ={ new DataGridComboBoxColumn { Header="dfsd", Binding=new DataGridBinding("p1",BindingMode.TwoWay),Width=100,Items={"0","1","2","3" } }, new DataGridCheckBoxColumn { Header="d1fsd", Binding=new DataGridBinding("p2"){ BindingMode= BindingMode.TwoWay },Width=100, }, new DataGridTextColumn { Header="3dfsd", Binding=new DataGridBinding("p3"){ BindingMode= BindingMode.TwoWay },Width="*" }, new DataGridTextColumn { Header="输入类型验证", Binding=new DataGridBinding("p4"){ BindingMode= BindingMode.TwoWay },Width="100" }, new DataGridTextColumn { Header="dfsd", Binding=new DataGridBinding("p5"),Width=100 }, }, Bindings = { { nameof(DataGrid.Items), nameof(Model.Data) } } };
如果要往里面加按钮和其他元素,添加 DataGridTemplateColumn 列,自定义单元格模板继承DataGridCellTemplat模板设置到CellTemplate属性,
new DataGridTemplateColumn{Hearder=”da”,Width=100,CellTemplate=typeof(XXXX)}
Picture
用来显示图片的元素,Source属性,可以直接设置URL和文件路径,也可以设置byte[]和Stream的图片数据。res://开头的是读取内嵌资源,区分大小写
Stretch和StretchDirection 缩放填充模式和WPF里的一样的。
Popup
用来做提示的窗体,ToolTip,右键菜单,下拉框等等就是用这个来做的。
PlacementTarget属性定义弹出的时候位置相对该元素
Placement 属性Popup 控件打开时的控件方向,并指定 Popup 控件在与屏幕边界重叠时的控件行为
Margin 用于调整相对位置的偏移
ContextMenu
Items可以直接绑定数据和ListBox那些一致或者加MenuItem,Separator(分割线)
设置给其他控件的ContextMenu属性
ScrollViewer
表示可包含其他可视元素的可滚动区域。元素加到Content,当元素范围超过ScrollViewer将出现滚动条
HorizontalScrollBarVisibility,VerticalScrollBarVisibility 滚动条可见性控制
VerticalOffset、HorizontalOffset 滚动偏移的获取或者设置
TabControl
Items里加TabItem
new TabControl { Items = { new TabItem { Content = new Panel { Height = "100%", Width = "100%", }, Header = "TabItem", }, }, Height = 104, Width = 167, },
TabIitem的Header属性可以添加UI元素,可以直接在设计器里添加控件组,用来实现图标加文字或者加关闭按钮等等的效果
SwitchAction属性可以定义切换的动画
SwitchAction = (oldItem, newItem) => { if (oldItem != null && oldItem.ContentElement != null) { oldItem.ContentElement.TransitionValue(nameof(UIElement.MarginLeft), (FloatField)"-100%", TimeSpan.FromSeconds(0.2), new PowerEase(), AnimateMode.EaseOut, () => { oldItem.ContentElement.Visibility = Visibility.Collapsed; }); } if (newItem != null && newItem.ContentElement != null) { newItem.ContentElement.Visibility = Visibility.Visible; newItem.ContentElement.MarginLeft = "100%"; newItem.ContentElement.TransitionValue(nameof(UIElement.MarginLeft), (FloatField)"0%", TimeSpan.FromSeconds(0.2), new PowerEase(), AnimateMode.EaseOut); } }
TextBlock Label
最基本的文本显示元素,Text属性设置显示的字符。一般建议直接使用TextBlock ,TextBlock 属于最基础的文本控件,Label属于复合控件可以修改模板。
TextBlock 的TextTrimming 可以设置溢出省略号
TextBox
文本输入控件,支持图文复制粘贴显示。
作为单行文本框需要设置这些属性,高度调小一些
AcceptsReturn: false;
AcceptsTab :false;
HScrollBarVisibility:Hidden;
VScrollBarVisibility :Hidden;
Padding 可以调整文本到边框的边距
Document 属性用来处理稍微复杂的文档元素,比如实现QQ气泡
Window
支持任意透明,对于部分Linux上黑底问题,需要Linux开启桌面合成,默认是不带窗体框架的(标题栏,系统按钮,阴影等),如果需要窗体框架,里面加WindowFrame
ShowDialog()是异步写法,ShowDialogSync 是同步写法
WindowFrame
通用窗体框架,包含窗体边框,系统按钮,阴影这些元素。默认的Window是没有系统按钮那些元素的,加入这个WindowFrame就有了。除了做*的窗体外,你可以用这个做定义的内嵌窗体,自定义内嵌窗体需要实现IWindow接口
MaximizeBox是否显示最大化还原按钮
MinimizeBox是否显示最小化
DockPanel
布局容器,里面的子元素设置附加属性 DockPanel.Dock 定义停靠行为
Grid
网格布局容器,里面的子元素设置附加属性 Grid. RowIndex Grid. ColumnIndex Grid. RowSpan(跨越的行的数量,默认值1) Grid. ColumnSpan(跨越列的数量,默认值1) 定义布局行为
ColumnDefinitions,RowDefinitions 列和行,宽度和高度支持权重*或者固定的数值
new Grid { BorderStroke = "1,Solid", BorderFill = "#959595", PresenterFor = this, Name = "testGrid", ColumnDefinitions = { new ColumnDefinition { }, new ColumnDefinition { }, }, Children = { new GridSplitter { Height = "100%", MarginLeft = 0f, Attacheds = { { Grid.ColumnIndex, 1 }, }, }, new Border { BorderThickness = "1,2,1,1", BorderType = BorderType.BorderThickness, MarginLeft = 69, Height = 37, Width = 47, }, }, Height = 147, Width = 165, }
MessageBox.Show()
默认弹窗,需要主窗体存在的时候才能使用,样式继承主窗体或者设置的Owner
SVG
Source属性,可以是svg文件的地址,路径,可以内嵌或者网络的。也可以直接把SVG的文档字符传入,比如<svg>…….</svg>的svg文档
支持显示SVG图形,暂时不支持里面的滤镜,动画,图片引用,文字等,只能显示简单的图形,一般作为矢量图标来使用。对于一些无法显示的svg,可以找svg编辑工具转换一下
图像缩放方式和Picture控件的一样
Switch
开关按钮,OnColor,OffColor 定义开和关的颜色
DatePicker,TimePicker
日期和时间控件
LayerDialog
定义一个遮罩弹出层对话框
new LayerDialog { Width = 400, Height = 300, Content = new Button { Content = "测试" } }.ShowDialog(this);
LoadingBox
定义一个遮罩加载动画。下面的是扩展方法,需要using CPF;
// 定义一个加载动画,你可以将耗时操作放到work委托里,可以异步等待返回一个值。里面可以执行多个分段的任务,并且刷新Message。 var r = await this.ShowLoading("开始加载...",a => { System.Threading.Thread.Sleep(1000); a.Message = "加载组件1..."; System.Threading.Thread.Sleep(1000); a.Message = "加载组件2..."; System.Threading.Thread.Sleep(1000); return "结果"; });
Chart
支持折线,曲线,条形的显示,支持缩放滚动
new Chart { GridShowMode = GridShowMode.Horizontal, GridFill = "#A5A5A5", YAxisScaleCount = 3, ChartFill = "#C7E5F6", CanScroll = true, IsAntiAlias = true, Height = 184, Width = 245, XAxis= { "1", "2", "3", "4", "5", "6", "7", "8", "9", "1", "2", "3", "4", "5", "6", "7", "8", "9", }, Data = { new ChartBarData { Name="test", Fill="#faf", Format="#\'%\'", Data = { 1, 2, 3 } }, new ChartBarData { Name="test1", Fill="#0af", Format="#\'%\'", ShowValueTip=true, Data = { 4, 5, 2 } }, new ChartLineData { Name="test2", LineFill="#a0f", Format="#\'%\'", LineType= LineTypes.Curve, BottomFill="#ff000033",//ShowValueTip=true, Data = { 4, 5, 2, 3, 4, 3, 4, 5, 2, 3, 4, 3, } }, new ChartLineData { Name="test2测试", LineFill="#0a0", BottomFill="#00000055", Data = { 3, 4, 5, 4, 3, 5, 3, 4, 5, 4, 3, 5, 5, 3, 4, 5, 4, 6, 5 } }, } },
PieChart
支持饼图,圆环图
new PieChart { RingWidth = "40%", Height = 219, Width = 279, IsAntiAlias=true, Data = { new PieChartData { Name="test1", Fill="#ff000055", Value=3 }, new PieChartData { Name="test2", Fill="#00ff0055", Value=5 }, new PieChartData { Name="test3", Fill="#0000ff55", Value=5 }, new PieChartData { Name="test4", Fill="#00ffff55", Value=5 }, new PieChartData { Name="test5", Fill="#a0fa0f55", Value=1 }, } },
NotifyIcon
系统托盘图标或者状态栏图标,不是所有系统都支持,部分Linux上不支持显示。
一般定义个全局的NotifyIcon对象就行,不需要添加到窗体上
NumericUpDown
用于设置数值的控件,Maximum,Minimum,Value 最大值,最小值,当前值
Slider
Expander
可折叠内容显示窗口的标题
new Expander { Header="test", Content= new Button { Content="test内容" } }
VideoView
视频播放控件,Nuget 安装Xhm.CPF.Vcl 然后使用VideoView控件,控件初始化之后使用MediaPlayer属性来对播放器进行详细控制。VideoView. LibVLC一些对象构造需要
new VideoView { Name = "player", PresenterFor=this, MarginBottom=0, MarginLeft=0, MarginRight=0, MarginTop=0, } player.Play(new Uri(@"http://*****.mp4"));//播放 player.MediaPlayer.Pause();//暂停
Vlc封装参考 https://github.com/videolan/libvlcsharp
Windows
Nuget 安装 VideoLAN.LibVLC.Windows
Mac
Nuget 安装 VideoLAN.LibVLC.Mac
Linux上需要安装
For ubuntu:
apt-get install libvlc-dev
apt-get install vlc
WebBrowser
封装cef的浏览器控件
需要安装Nuget包
<PackageReference Include="Xhm.CPF.Cef" Version="0.9" />
到 https://cef-builds.spotifycdn.com/index.html#windows64:88.1.6%2Bg4fe33a1%2Bchromium-88.0.4324.96 下载对应平台的二进制文件,一般是选择 Sample Application ......client.tar.bz2
注意版本号:88.1.6+g4fe33a1+chromium-88.0.4324.96
需要注意的是如果你需要的是Linux平台的,建议自己调整编译参数重新编译,因为网站上下载的二进制文件巨大,达到一个G了
一般情况下,把压缩包里的比如libcef...同目录里的所有文件和文件夹都复制到你的程序目录就行
如果是Mac的话
将文件\Release\Chromium Embedded Framework.framework\Chromium Embedded Framework复制到你的程序目录并重命名为libcef.dylib
将“\Release\Chromium Embedded Framework.framework\Libraries”文件夹中的所有文件和文件夹复制你的程序目录
将“\Release\Chromium Embedded Framework.framework\Resources”文件夹中的所有文件和文件夹复制到你的程序目录
如果你需要支持视频播放,那你需要自己修改编译参数,重新编译才行,具体教程可以百度
如果你想自定义特殊功能,比如拦截请求,你需要继承 WebBrowser,并重写 OnCreateWebBrowser
OnCreateWebBrowser里面写client.LoadHandler = new CpfCefLoadHandler();继承并重写对应的Handler并设置过来
mac上运行在任务栏上可能会有多个图标闪烁之后就没了,是正常的,cef的多进程问题,不影响使用
想修改控件元素和效果?继承你要修改的控件,然后重写InitializeComponent 把定义代码写在里面,不知道怎么定义?设计器,右键模板库,基础控件模板,选择后自动添加,自己根据需要修改。模板中使用PresenterFor 属性是为了区分该对象是否是该模板对象内部使用的。单纯的用name来区分的话会出现错误,因为name会有重复,尤其是多种复杂对象嵌套的时候。