干!垃圾微软!发布我的Netcore跨平台UI框架 CPF
(居然有人看不懂我的标题,1,我是嫌弃微软明明可以先发制人,却处处被动防守,2,我写的东西撞上微软了,就和做游戏的撞上腾讯一样,花那么多时间写的东西,要被大厂挤压掉了)
什么鬼,我的CPF快写好了,你居然也要搞跨平台UI框架?什么Maui? 之前怎么不早说要搞跨平台UI框架呢?看到谷歌搞flutter眼红了?明年年底发布?又搞这种追别人屁股的烂事情。
什么MVU模式?模仿Dart?用C#代码直接写UI的模式和我的CPF很像啊。
当初我考虑过XML,Json来描述UI,但是我感觉这些都是多余的累赘,而且还需要学习语法,感觉Xaml很啰嗦,如果有设计器的话,直接生成对应的UI代码不是更直接?而且用XML、Json需要多消耗解析UI代码的资源。
所以一开始我是模仿Winform直接用C#来描述的,不过Winform生成的代码很冗长,直接看这种代码很费劲,所以考虑优化代码结构,看看能否有既可以直接运行生成UI,既可以直观描述结构的
1 new Panel 2 { 3 ToolTip="最大化", 4 Name="max", 5 Width = 30, 6 Height = "100%", 7 Children= 8 { 9 new Rectangle 10 { 11 Width=14, 12 Height=12, 13 StrokeStyle="2", 14 StrokeFill = "#fff" 15 } 16 }, 17 Commands = 18 { 19 { 20 nameof(Button.MouseDown),//可以绑定事件和属性通知 21 (s,e)=> 22 { 23 (e as MouseButtonEventArgs).Handled = true; 24 this.WindowState= WindowState.Maximized; 25 } 26 } 27 }, 28 Bindings = //数据绑定 29 { 30 { 31 nameof(Border.Visibility), 32 nameof(Window.WindowState), 33 this, 34 BindingMode.OneWay,//直接使用Lambda表达式作为数据转换器 35 a => (WindowState)a == WindowState.Maximized ? Visibility.Collapsed : Visibility.Visible 36 } 37 }, 38 Triggers= 39 { 40 new Trigger(nameof(Panel.IsMouseOver), Relation.Me)//触发器可以设置相对位置的其他元素的属性 41 { 42 Setters = 43 { 44 { 45 nameof(Panel.Background), 46 "#fff" 47 } 48 } 49 } 50 }, 51 }
这种结构感觉还行吧,微软的Maui的Mvu模式,感觉和我的很像,而且mvu的最终格式还没确定。现在maui那边定义的规则似乎是以方法为主,而我的是以属性为主,稍微封装几个扩展方法也可以变成maui那样的。
另外Mvu模式似乎不提供拖拽的设计器,只提供预览而已。
CPF的不仅可以预览,还可以拖拽,设置属性,生成C#代码。支持SVG显示。
CPF不提供Xaml描述UI,另外CPF提供CSS来描述样式,类似于Unity3D里的USS。
为什么使用CSS来描述?因为CSS结构简单,简洁明了,方便对多个元素声明属性,也方便代码复用。比Xaml里的样式描述简洁多了。学习成本低,主要会几个常用的选择器就行
* { FontFamily: 微软雅黑; } @keyframes buttonAnimationEnter { 0% { Background: #1E9FFF; } 100% { Background: rgb(75,178,255); } } #DropDownPanel TextBlock { MarginLeft: 5; } Button { Background: #1E9FFF; Foreground: #fff; BorderFill: null; } Button[IsMouseOver=true] { Background: #1E9FFF; animation-name: buttonAnimationEnter; animation-duration: 0.2s; animation-iteration-count: 1; animation-fill-mode: forwards; } Button[IsPressed=true] { Background: rgb(30,159,255); } CheckBox #indeterminateMark { Fill: #1E9FFF; } CheckBox #checkBoxBorder { Background: #fff; BorderFill: #1E9FFF; } CheckBox[IsChecked=true] #checkBoxBorder { Background: #1E9FFF; BorderFill: #1E9FFF; } CheckBox Polyline { StrokeFill: #fff; }
简化依赖属性写法
/// <summary> /// 前景色 /// </summary> [UIPropertyMetadata(typeof(ViewFill), "Black", UIPropertyOptions.AffectsRender)] public ViewFill Foreground { get { return (ViewFill)GetValue(); } set { SetValue(value); } }
简化附加属性写法
/// <summary> /// 获取或设置一个值,该值指示一个子元素在父级 DockPanel 中的位置。 附加属性 /// </summary> public static Attached<Dock> Dock { get { return RegisterAttached(Controls.Dock.Left, (CpfObject obj, string propertyName, object defaultValue, object oldValue, ref object newValue) => { if (obj is UIElement element && element.Parent != null) { element.Parent.InvalidateMeasure(); } }); } } var dock=DockPanel.Dock(button)//取值DockPanel.Dock(button,Dock.Left)//设置值
计算属性
计算属性来自Vue里的computed 可绑定,只读属性
当SelectValue或者TextSize属性值变化之后导致TestComputedProperty属性值变化,有提供属性通知
[Computed(nameof(SelectValue), nameof(TextSize))] public string TestComputedProperty { get { return SelectValue == null ? "" : SelectValue.ToString() + TextSize; } }
CPF已经完成了Windows,Mac和Linux,PC端的跨平台,移动端的还在计划中。
CPF、 Avalonia、 Maui一些对比
Avalonia是一个开源的跨平台的UI框架,用Xaml描述UI的。
CPF | Avalonia | Maui | |
最低框架依赖 | .net standard2.0/netcore2.0 | net4(支持XP) | .net standard2.0/netcore2.0 | Net6 |
当前状态 | 可用 | 可用 | 未发布,需要明年年底 |
独立发布的程序包大小 |
较小,依赖少,附带dll少,Windows端手动裁剪可以到20多M,包含运行时。 如果用net4版,可以更小,不过只能Windows端 |
稍微大一些,附带的dll多 |
估计会比较大,毕竟高版本的框架。 功能也更多。 |
UI开发模式 | C#+CSS | Xaml | Xaml MVU(C#) |
支持平台 | Windows,Mac,Linux,移动端暂时不支持 | Windows,Mac,Linux,移动端支持 | PC和移动端都支持 |
一些细节问题 | 多平台支持中文输入法,暂时不支持触摸事件,暂时不支持硬件加速 | 输入法支持度不够,支持触摸事件,支持硬件加速 | 支持 |
设计器 | 预览和拖拽 | 预览 | xaml预览和拖拽,mvu预览 |
布局控件
运行的时候,查看元素和调试
一份代码,两个目标框架支持,一部分代码通过编译条件符来区分
我也不敢说我的CPF有多完善,至少常用控件基本都有了,写写小工具,小应用还是可以的。之后会进一步完善。如果你想使用CPF,必须用VS2019,才能安装插件来做设计器预览,才能发布Netcore3。
dll免费,可以商业开发。
以后会陆续发布一些cpf的教程