干!垃圾微軟!發布我的Netcore跨平台UI框架 CPF
什麼鬼,我的CPF快寫好了,你居然也要搞跨平台UI框架?什麼Maui? 之前怎麼不早說要搞跨平台UI框架呢?看到Google搞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的教程