diff --git a/CPF.Razor/Controls/Button.cs b/CPF.Razor/Controls/Button.cs
new file mode 100644
index 0000000..68aac6d
--- /dev/null
+++ b/CPF.Razor/Controls/Button.cs
@@ -0,0 +1,14 @@
+using Microsoft.AspNetCore.Components;
+//using Microsoft.MobileBlazorBindings.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class Button
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/CheckBox.cs b/CPF.Razor/Controls/CheckBox.cs
new file mode 100644
index 0000000..5779cfa
--- /dev/null
+++ b/CPF.Razor/Controls/CheckBox.cs
@@ -0,0 +1,14 @@
+using Microsoft.AspNetCore.Components;
+//using Microsoft.MobileBlazorBindings.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class CheckBox
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/DockPanel.cs b/CPF.Razor/Controls/DockPanel.cs
new file mode 100644
index 0000000..85db5ee
--- /dev/null
+++ b/CPF.Razor/Controls/DockPanel.cs
@@ -0,0 +1,14 @@
+using Microsoft.AspNetCore.Components;
+//using Microsoft.MobileBlazorBindings.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class DockPanel
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/Element.cs b/CPF.Razor/Controls/Element.cs
index 5682382..2fc4c3b 100644
--- a/CPF.Razor/Controls/Element.cs
+++ b/CPF.Razor/Controls/Element.cs
@@ -93,6 +93,13 @@ namespace CPF.Razor.Controls
return r;
}
+ public void HandleText(int index, string text)
+ {
+ if (Element is CPF.Controls.ContentControl control)
+ {
+ control.Content = text;
+ }
+ }
////只要属性和事件自动生成就行
//[Parameter] public string Name { get; set; }
diff --git a/CPF.Razor/Controls/Grid.cs b/CPF.Razor/Controls/Grid.cs
new file mode 100644
index 0000000..a21e2f2
--- /dev/null
+++ b/CPF.Razor/Controls/Grid.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class Grid
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/Panel.cs b/CPF.Razor/Controls/Panel.cs
index 62d6351..7b2294e 100644
--- a/CPF.Razor/Controls/Panel.cs
+++ b/CPF.Razor/Controls/Panel.cs
@@ -10,9 +10,7 @@ namespace CPF.Razor.Controls
{
//[Parameter] public string Background { get; set; }
-#pragma warning disable CA1721 // Property names should not match get methods
[Parameter] public RenderFragment ChildContent { get; set; }
-#pragma warning restore CA1721 // Property names should not match get methods
- protected override RenderFragment GetChildContent() => ChildContent;
+ protected override RenderFragment GetChild() => ChildContent;
}
}
diff --git a/CPF.Razor/Controls/ResponsivePanel.cs b/CPF.Razor/Controls/ResponsivePanel.cs
new file mode 100644
index 0000000..7ef6b7b
--- /dev/null
+++ b/CPF.Razor/Controls/ResponsivePanel.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class ResponsivePanel
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/StackPanel.cs b/CPF.Razor/Controls/StackPanel.cs
index beec2e1..dc5d142 100644
--- a/CPF.Razor/Controls/StackPanel.cs
+++ b/CPF.Razor/Controls/StackPanel.cs
@@ -7,9 +7,7 @@ namespace CPF.Razor.Controls
{
public partial class StackPanel
{
-#pragma warning disable CA1721 // Property names should not match get methods
[Parameter] public RenderFragment ChildContent { get; set; }
-#pragma warning restore CA1721 // Property names should not match get methods
- protected override RenderFragment GetChildContent() => ChildContent;
+ protected override RenderFragment GetChild() => ChildContent;
}
}
diff --git a/CPF.Razor/Controls/WindowFrame.cs b/CPF.Razor/Controls/WindowFrame.cs
new file mode 100644
index 0000000..8906ff8
--- /dev/null
+++ b/CPF.Razor/Controls/WindowFrame.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class WindowFrame
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/WrapPanel.cs b/CPF.Razor/Controls/WrapPanel.cs
new file mode 100644
index 0000000..6980be7
--- /dev/null
+++ b/CPF.Razor/Controls/WrapPanel.cs
@@ -0,0 +1,14 @@
+using Microsoft.AspNetCore.Components;
+//using Microsoft.MobileBlazorBindings.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CPF.Razor.Controls
+{
+ public partial class WrapPanel
+ {
+ [Parameter] public RenderFragment ChildContent { get; set; }
+ protected override RenderFragment GetChild() => ChildContent;
+ }
+}
diff --git a/CPF.Razor/Controls/generated/Button.generated.cs b/CPF.Razor/Controls/generated/Button.generated.cs
index 49ab720..0a7462b 100644
--- a/CPF.Razor/Controls/generated/Button.generated.cs
+++ b/CPF.Razor/Controls/generated/Button.generated.cs
@@ -13,7 +13,7 @@ namespace CPF.Razor.Controls
///
/// 表示 Windows 按钮控件,该按钮对 Click 事件做出反应。
///
- public partial class Button : Element
+ public partial class Button : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/CheckBox.generated.cs b/CPF.Razor/Controls/generated/CheckBox.generated.cs
index 4db9ff4..ba6182c 100644
--- a/CPF.Razor/Controls/generated/CheckBox.generated.cs
+++ b/CPF.Razor/Controls/generated/CheckBox.generated.cs
@@ -14,7 +14,7 @@ namespace CPF.Razor.Controls
///
/// 表示用户可以选择和清除的控件。
///
- public partial class CheckBox : Element
+ public partial class CheckBox : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/Expander.generated.cs b/CPF.Razor/Controls/generated/Expander.generated.cs
index 70a944b..2cc7bab 100644
--- a/CPF.Razor/Controls/generated/Expander.generated.cs
+++ b/CPF.Razor/Controls/generated/Expander.generated.cs
@@ -13,7 +13,7 @@ namespace CPF.Razor.Controls
///
/// 表示一种控件,该控件显示具有可折叠内容显示窗口的标题。
///
- public partial class Expander : Element
+ public partial class Expander : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/RadioButton.generated.cs b/CPF.Razor/Controls/generated/RadioButton.generated.cs
index 07a1266..d84bb24 100644
--- a/CPF.Razor/Controls/generated/RadioButton.generated.cs
+++ b/CPF.Razor/Controls/generated/RadioButton.generated.cs
@@ -14,7 +14,7 @@ namespace CPF.Razor.Controls
///
/// 表示可由用户选择但不能清除的按钮。 可以通过单击来设置 IsChecked 的 RadioButton 属性,但只能以编程方式清除该属性。
///
- public partial class RadioButton : Element
+ public partial class RadioButton : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/RepeatButton.generated.cs b/CPF.Razor/Controls/generated/RepeatButton.generated.cs
index 19a43d3..21891fb 100644
--- a/CPF.Razor/Controls/generated/RepeatButton.generated.cs
+++ b/CPF.Razor/Controls/generated/RepeatButton.generated.cs
@@ -13,7 +13,7 @@ namespace CPF.Razor.Controls
///
/// 表示从按下按钮到释放按钮的时间内重复引发其 Click 事件的控件。
///
- public partial class RepeatButton : Element
+ public partial class RepeatButton : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/ScrollViewer.generated.cs b/CPF.Razor/Controls/generated/ScrollViewer.generated.cs
index c4edf25..ad9a77e 100644
--- a/CPF.Razor/Controls/generated/ScrollViewer.generated.cs
+++ b/CPF.Razor/Controls/generated/ScrollViewer.generated.cs
@@ -13,7 +13,7 @@ namespace CPF.Razor.Controls
///
/// 表示可包含其他可视元素的可滚动区域
///
- public partial class ScrollViewer : Element
+ public partial class ScrollViewer : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/Switch.generated.cs b/CPF.Razor/Controls/generated/Switch.generated.cs
index 6aad4bd..1de9c26 100644
--- a/CPF.Razor/Controls/generated/Switch.generated.cs
+++ b/CPF.Razor/Controls/generated/Switch.generated.cs
@@ -14,7 +14,7 @@ namespace CPF.Razor.Controls
///
/// 左右切换的按钮
///
- public partial class Switch : Element
+ public partial class Switch : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/ToggleButton.generated.cs b/CPF.Razor/Controls/generated/ToggleButton.generated.cs
index 1a9807b..031b931 100644
--- a/CPF.Razor/Controls/generated/ToggleButton.generated.cs
+++ b/CPF.Razor/Controls/generated/ToggleButton.generated.cs
@@ -14,7 +14,7 @@ namespace CPF.Razor.Controls
///
/// 可切换状态的控件基类
///
- public partial class ToggleButton : Element
+ public partial class ToggleButton : Element ,IHandleChildContentText
{
///
diff --git a/CPF.Razor/Controls/generated/WindowFrame.generated.cs b/CPF.Razor/Controls/generated/WindowFrame.generated.cs
new file mode 100644
index 0000000..f884eb2
--- /dev/null
+++ b/CPF.Razor/Controls/generated/WindowFrame.generated.cs
@@ -0,0 +1,80 @@
+// CPF自动生成.
+
+using CPF;
+using CPF.Controls;
+using CPF.Drawing;
+using CPF.Input;
+using CPF.Razor;
+using CPF.Shapes;
+using Microsoft.AspNetCore.Components;
+
+namespace CPF.Razor.Controls
+{
+ ///
+ /// 通用窗体框架,包含窗体边框,系统按钮,阴影这些元素
+ ///
+ public partial class WindowFrame : Element
+ {
+
+ ///
+ /// 背景填充
+ ///
+ [Parameter] public string Background { get; set; }
+ ///
+ /// 边框线条填充
+ ///
+ [Parameter] public string BorderFill { get; set; }
+ ///
+ /// 获取或设置线条类型
+ ///
+ [Parameter] public Stroke? BorderStroke { get; set; }
+ ///
+ /// 四周边框粗细
+ ///
+ [Parameter] public Thickness? BorderThickness { get; set; }
+ ///
+ /// 边框类型,BorderStroke和BorderThickness
+ ///
+ [Parameter] public BorderType? BorderType { get; set; }
+ ///
+ /// 获取或设置一个值,该值表示将 Border 的角倒圆的程度。格式 一个数字或者四个数字 比如10或者 10,10,10,10 topLeft,topRight,bottomRight,bottomLeft
+ ///
+ [Parameter] public CornerRadius? CornerRadius { get; set; }
+ ///
+ /// 字体名
+ ///
+ [Parameter] public string FontFamily { get; set; }
+ ///
+ /// 字体尺寸,点
+ ///
+ [Parameter] public float? FontSize { get; set; }
+ ///
+ /// 字体样式
+ ///
+ [Parameter] public FontStyles? FontStyle { get; set; }
+ ///
+ /// 控件文字的填充
+ ///
+ [Parameter] public string Foreground { get; set; }
+ [Parameter] public bool? MaximizeBox { get; set; }
+ [Parameter] public bool? MinimizeBox { get; set; }
+ ///
+ /// 获取或设置描述 Thickness 及其子元素之间的空间量的 Border 值。格式:all或者left,top,right,bottom
+ ///
+ [Parameter] public Thickness? Padding { get; set; }
+ ///
+ /// 阴影宽度
+ ///
+ [Parameter] public byte? ShadowBlur { get; set; }
+ ///
+ /// 显示标题栏图标
+ ///
+ [Parameter] public bool? ShowIcon { get; set; }
+ ///
+ /// 表示一个文本修饰,它是可添加到文本的视觉装饰(如下划线)。字符串格式: overline/Underline/Strikethrough/none [width[,Solid/Dash/Dot/DashDot/DashDotDot]] [color]
+ ///
+ [Parameter] public TextDecoration? TextDecoration { get; set; }
+ [Parameter] public EventCallback Initialized { get; set; }
+
+ }
+}
diff --git a/CPF.Razor/Core/NativeControlComponentBase.cs b/CPF.Razor/Core/NativeControlComponentBase.cs
index 33e69fb..4af512a 100644
--- a/CPF.Razor/Core/NativeControlComponentBase.cs
+++ b/CPF.Razor/Core/NativeControlComponentBase.cs
@@ -50,7 +50,7 @@ namespace CPF.Razor
builder.OpenElement(0, GetType().FullName);
RenderAttributes(new AttributesBuilder(builder));
- var childContent = GetChildContent();
+ var childContent = GetChild();
if (childContent != null)
{
builder.AddContent(2, childContent);
@@ -63,7 +63,7 @@ namespace CPF.Razor
{
}
- protected virtual RenderFragment GetChildContent() => null;
+ protected virtual RenderFragment GetChild() => null;
public abstract void ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName);
diff --git a/CPF.Razor/CpfElementManager.cs b/CPF.Razor/CpfElementManager.cs
index 9dab84c..e76679d 100644
--- a/CPF.Razor/CpfElementManager.cs
+++ b/CPF.Razor/CpfElementManager.cs
@@ -31,7 +31,7 @@ namespace CPF.Razor
panel.Children.Add(childHandler.Element);
}
}
- else if (parentHandler.Element is CPF.Controls.Window win)
+ else if (parentHandler.Element is CPF.Controls.View win)
{
if (physicalSiblingIndex <= win.Children.Count)
{
@@ -64,6 +64,14 @@ namespace CPF.Razor
{
panel.Children.Remove(handler.Element);
}
+ else if (handler.Element.Parent is CPF.Controls.View win)
+ {
+ win.Children.Remove(handler.Element);
+ }
+ else if (handler.Element.Parent is CPF.Controls.ContentControl contentControl)
+ {
+ contentControl.Content = null;
+ }
else
{
Debug.Fail("未实现移除控件");
diff --git a/CPF/Controls/WindowFrame.cs b/CPF/Controls/WindowFrame.cs
index 818dd9e..50d445a 100644
--- a/CPF/Controls/WindowFrame.cs
+++ b/CPF/Controls/WindowFrame.cs
@@ -17,7 +17,7 @@ namespace CPF.Controls
/// 通用窗体框架,包含窗体边框,系统按钮,阴影这些元素
///
[Description("通用窗体框架,包含窗体边框,系统按钮,阴影这些元素")]
- public class WindowFrame : Control
+ public class WindowFrame : ContentControl
{
///
/// 通用窗体框架,包含窗体边框,系统按钮,阴影这些元素
@@ -28,11 +28,11 @@ namespace CPF.Controls
public WindowFrame(IWindow window, UIElement content, params UIElement[] systemButtons)
{
this.window = window;
- this.content = content;
+ this.Content = content;
this.systemButtons = systemButtons;
}
- protected WindowFrame() { }
+ public WindowFrame() { }
///
/// 是否显示最大化还原按钮
@@ -54,15 +54,15 @@ namespace CPF.Controls
get { return window; }
}
- UIElement content;
- ///
- /// 窗体的内容
- ///
- [NotCpfProperty]
- public UIElement Content
- {
- get { return content; }
- }
+ //UIElement content;
+ /////
+ ///// 窗体的内容
+ /////
+ //[NotCpfProperty]
+ //public UIElement Content
+ //{
+ // get { return content; }
+ //}
IEnumerable systemButtons;
///
@@ -96,7 +96,7 @@ namespace CPF.Controls
protected override void InitializeComponent()
{
-
+
ViewFill color = "#fff";
ViewFill hoverColor = "255,255,255,40";
Width = "100%";
@@ -142,6 +142,8 @@ namespace CPF.Controls
{
Width = "100%",
Height = "100%",
+ Name = "contentGrid",
+ PresenterFor = this,
ColumnDefinitions =
{
new ColumnDefinition()
@@ -157,6 +159,19 @@ namespace CPF.Controls
}
},
+ Children =
+ {
+ new Border
+ {
+ Name = "contentPresenter",
+ Height = "100%",
+ Width = "100%",
+ BorderFill = null,
+ BorderStroke="0",
+ PresenterFor = this,
+ [Grid.RowIndex]=1,
+ }
+ }
});
//标题栏和按钮
grid.Children.Add(
@@ -237,6 +252,7 @@ namespace CPF.Controls
new StackPanel
{
Name="controlBox",
+ PresenterFor=this,
MarginRight=0,
Height = "100%",
Orientation= Orientation.Horizontal,
@@ -495,10 +511,10 @@ namespace CPF.Controls
}
}
});
- if (Content != null)
- {
- grid.Children.Add(Content, 0, 1);
- }
+ //if (Content != null)
+ //{
+ // grid.Children.Add(Content, 0, 1);
+ //}
}
protected void DoubleClickTitle()
@@ -515,6 +531,25 @@ namespace CPF.Controls
}
}
+ protected override void OnAttachedToVisualTree()
+ {
+ var parent = Parent;
+ while (parent != null)
+ {
+ if (parent is IWindow window)
+ {
+ this.window = window;
+ break;
+ }
+ parent = parent.Parent;
+ }
+ if (window == null)
+ {
+ window = (IWindow)Root;
+ }
+ base.OnAttachedToVisualTree();
+ }
+
}
///
/// 通用窗体接口
diff --git a/CpfRazorSample/ComponentWrapperGenerator/CpfComponentWrapperGenerator.cs b/CpfRazorSample/ComponentWrapperGenerator/CpfComponentWrapperGenerator.cs
new file mode 100644
index 0000000..1269da0
--- /dev/null
+++ b/CpfRazorSample/ComponentWrapperGenerator/CpfComponentWrapperGenerator.cs
@@ -0,0 +1,636 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Windows.Input;
+
+namespace ComponentWrapperGenerator
+{
+ // TODO: XML Doc Comments
+
+#pragma warning disable CA1724 // Type name conflicts with namespace name
+ public class CpfComponentWrapperGenerator
+#pragma warning restore CA1724 // Type name conflicts with namespace name
+ {
+ public CpfComponentWrapperGenerator(GeneratorSettings settings)
+ {
+ Settings = settings ?? throw new ArgumentNullException(nameof(settings));
+ }
+
+ private GeneratorSettings Settings { get; }
+
+ public void GenerateComponentWrapper(Type typeToGenerate, string outputFolder)
+ {
+ typeToGenerate = typeToGenerate ?? throw new ArgumentNullException(nameof(typeToGenerate));
+
+ var propertiesToGenerate = GetPropertiesToGenerate(typeToGenerate);
+
+ GenerateComponentFile(typeToGenerate, propertiesToGenerate, outputFolder);
+ //GenerateHandlerFile(typeToGenerate, propertiesToGenerate, outputFolder);
+ }
+
+ private void GenerateComponentFile(Type typeToGenerate, IEnumerable propertiesToGenerate, string outputFolder)
+ {
+ var fileName = Path.Combine(outputFolder, $"{typeToGenerate.Name}.generated.cs");
+ var directoryName = Path.GetDirectoryName(fileName);
+ if (!string.IsNullOrEmpty(directoryName))
+ {
+ Directory.CreateDirectory(directoryName);
+ }
+
+ Console.WriteLine($"Generating component for type '{typeToGenerate.FullName}' into file '{fileName}'.");
+
+ var componentName = typeToGenerate.Name;
+ //var componentHandlerName = $"{componentName}Handler";
+ //var componentBaseName = GetBaseTypeOfInterest(typeToGenerate).Name;
+ var componentBaseName = $": Element<{typeToGenerate.FullName}>";
+ if (typeToGenerate.IsSubclassOf(typeof(CPF.Controls.ContentControl)))
+ {
+ componentBaseName += " ,IHandleChildContentText";
+ }
+ if (componentName == "UIElement")
+ {
+ componentName = "Element";
+ componentBaseName = "";
+ }
+
+ // header
+ var headerText = Settings.FileHeader;
+
+ // usings
+ var usings = new List
+ {
+ new UsingStatement { Namespace = "Microsoft.AspNetCore.Components" },
+ new UsingStatement { Namespace = "CPF" },
+ new UsingStatement { Namespace = "CPF.Input" },
+ new UsingStatement { Namespace = "CPF.Shapes" },
+ new UsingStatement { Namespace = "CPF.Razor" },
+ new UsingStatement { Namespace = "CPF.Drawing" },
+ new UsingStatement { Namespace = "CPF.Controls" },
+ new UsingStatement { Namespace = "CPF.Razor.Controls" }
+ };
+
+ // props
+ var propertyDeclarationBuilder = new StringBuilder();
+ if (propertiesToGenerate.Any())
+ {
+ propertyDeclarationBuilder.AppendLine();
+ }
+ foreach (var prop in propertiesToGenerate)
+ {
+ propertyDeclarationBuilder.Append(GetPropertyDeclaration(prop, usings));
+ }
+
+ var events = typeToGenerate.GetEvents(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var prop in events)
+ {
+ if (typeToGenerate == typeof(CPF.UIElement) || (typeToGenerate != typeof(CPF.UIElement) && prop.DeclaringType != typeof(CPF.UIElement) && prop.DeclaringType != typeof(CPF.Visual) && prop.DeclaringType != typeof(CPF.CpfObject)))
+ {
+ propertyDeclarationBuilder.Append(GetEventDeclaration(prop, usings));
+ }
+ }
+
+ var propertyDeclarations = propertyDeclarationBuilder.ToString();
+
+ //var propertyAttributeBuilder = new StringBuilder();
+ //foreach (var prop in propertiesToGenerate)
+ //{
+ // propertyAttributeBuilder.Append(GetPropertyRenderAttribute(prop));
+ //}
+ //var propertyAttributes = propertyAttributeBuilder.ToString();
+ //var eventHandlerAttributes = "";
+
+ var usingsText = string.Join(
+ Environment.NewLine,
+ usings
+ .Distinct()
+ .Where(u => u.Namespace != Settings.RootNamespace)
+ .OrderBy(u => u.ComparableString)
+ .Select(u => u.UsingText));
+
+ var isComponentAbstract = typeToGenerate.IsAbstract;
+ var classModifiers = string.Empty;
+ if (isComponentAbstract)
+ {
+ classModifiers += "abstract ";
+ }
+ var componentHasPublicParameterlessConstructor =
+ typeToGenerate
+ .GetConstructors()
+ .Any(ctor => ctor.IsPublic && !ctor.GetParameters().Any());
+
+ var des = "";
+ var d = typeToGenerate.GetCustomAttribute();
+ if (d != null)
+ {
+ des = d.Description;
+ }
+
+ var outputBuilder = new StringBuilder();
+ outputBuilder.Append($@"{headerText}
+{usingsText}
+
+namespace {Settings.RootNamespace}
+{{
+ ///
+ /// {des}
+ ///
+ public {classModifiers}partial class {componentName} {componentBaseName}
+ {{
+ {propertyDeclarations}
+ }}
+}}
+");
+
+ File.WriteAllText(fileName, outputBuilder.ToString());
+ }
+
+ //private static readonly List DisallowedComponentPropertyTypes = new List
+ //{
+ // typeof(XF.Button.ButtonContentLayout), // TODO: This is temporary; should be possible to add support later
+ // typeof(XF.ColumnDefinitionCollection),
+ // typeof(XF.ControlTemplate),
+ // typeof(XF.DataTemplate),
+ // typeof(XF.Element),
+ // typeof(XF.Font), // TODO: This is temporary; should be possible to add support later
+ // typeof(XF.FormattedString),
+ // typeof(ICommand),
+ // typeof(XF.Keyboard), // TODO: This is temporary; should be possible to add support later
+ // typeof(object),
+ // typeof(XF.Page),
+ // typeof(XF.ResourceDictionary),
+ // typeof(XF.RowDefinitionCollection),
+ // typeof(XF.ShellContent),
+ // typeof(XF.ShellItem),
+ // typeof(XF.ShellSection),
+ // typeof(XF.Style), // TODO: This is temporary; should be possible to add support later
+ // typeof(XF.IVisual),
+ // typeof(XF.View),
+ //};
+
+ private static string GetPropertyDeclaration(PropertyInfo prop, IList usings)
+ {
+ var propertyType = prop.PropertyType;
+ string propertyTypeName;
+ if (propertyType == typeof(IList) || propertyType == typeof(CPF.ViewFill) || propertyType == typeof(CPF.Drawing.Color) || propertyType == typeof(CPF.Drawing.Brush))
+ {
+ // Lists of strings are special-cased because they are handled specially by the handlers as a comma-separated list
+ propertyTypeName = "string";
+ }
+ else
+ {
+ propertyTypeName = GetTypeNameAndAddNamespace(propertyType, usings);
+ if (propertyType.IsValueType && (!propertyType.IsGenericType || propertyType.GetGenericTypeDefinition() == typeof(Nullable)))
+ {
+ propertyTypeName += "?";
+ }
+ }
+ var des = "";
+ var d = prop.GetCustomAttribute();
+ if (d != null)
+ {
+ des = $" /// \r\n /// {d.Description}\r\n /// \r\n";
+ }
+ return $@"{des} [Parameter] public {propertyTypeName} {GetIdentifierName(prop.Name)} {{ get; set; }}
+";
+ }
+
+ private static string GetEventDeclaration(EventInfo prop, IList usings)
+ {
+ var propertyType = prop.EventHandlerType;
+ string propertyTypeName;
+ if (propertyType == typeof(EventHandler))
+ {
+ // Lists of strings are special-cased because they are handled specially by the handlers as a comma-separated list
+ propertyTypeName = "EventCallback";
+ }
+ else
+ {
+ //propertyTypeName = GetTypeNameAndAddNamespace(propertyType, usings);
+ //if (propertyType.IsValueType)
+ //{
+ // propertyTypeName += "?";
+ //}
+ propertyTypeName = $"EventCallback<{propertyType.GetGenericArguments()[0]}>";
+ }
+ var des = "";
+ var d = prop.GetCustomAttribute();
+ if (d != null)
+ {
+ des = $" /// \r\n /// {d.Description}\r\n /// \r\n";
+ }
+ return $@"{des} [Parameter] public {propertyTypeName} {GetIdentifierName(prop.Name)} {{ get; set; }}
+";
+ }
+
+ private static string GetTypeNameAndAddNamespace(Type type, IList usings)
+ {
+ var typeName = GetCSharpType(type);
+ if (typeName != null)
+ {
+ return typeName;
+ }
+
+ // Check if there's a 'using' already. If so, check if it has an alias. If not, add a new 'using'.
+ var namespaceAlias = string.Empty;
+
+ var existingUsing = usings.FirstOrDefault(u => u.Namespace == type.Namespace);
+ if (existingUsing == null)
+ {
+ usings.Add(new UsingStatement { Namespace = type.Namespace });
+ }
+ else
+ {
+ if (existingUsing.Alias != null)
+ {
+ namespaceAlias = existingUsing.Alias + ".";
+ }
+ }
+ typeName = namespaceAlias + FormatTypeName(type, usings);
+ return typeName;
+ }
+
+ private static string FormatTypeName(Type type, IList usings)
+ {
+ if (!type.IsGenericType)
+ {
+ return type.Name;
+ }
+ var typeNameBuilder = new StringBuilder();
+ typeNameBuilder.Append(type.Name.Substring(0, type.Name.IndexOf('`', StringComparison.Ordinal)));
+ typeNameBuilder.Append("<");
+ var genericArgs = type.GetGenericArguments();
+ for (int i = 0; i < genericArgs.Length; i++)
+ {
+ if (i > 0)
+ {
+ typeNameBuilder.Append(", ");
+ }
+ typeNameBuilder.Append(GetTypeNameAndAddNamespace(genericArgs[i], usings));
+
+ }
+ typeNameBuilder.Append(">");
+ return typeNameBuilder.ToString();
+ }
+
+ //private static readonly Dictionary> TypeToAttributeHelperGetter = new Dictionary>
+ //{
+ // { typeof(XF.Color), propValue => $"AttributeHelper.ColorToString({propValue})" },
+ // { typeof(XF.CornerRadius), propValue => $"AttributeHelper.CornerRadiusToString({propValue})" },
+ // { typeof(XF.ImageSource), propValue => $"AttributeHelper.ImageSourceToString({propValue})" },
+ // { typeof(XF.LayoutOptions), propValue => $"AttributeHelper.LayoutOptionsToString({propValue})" },
+ // { typeof(XF.Thickness), propValue => $"AttributeHelper.ThicknessToString({propValue})" },
+ // { typeof(bool), propValue => $"{propValue}" },
+ // { typeof(double), propValue => $"AttributeHelper.DoubleToString({propValue})" },
+ // { typeof(float), propValue => $"AttributeHelper.SingleToString({propValue})" },
+ // { typeof(int), propValue => $"{propValue}" },
+ // { typeof(string), propValue => $"{propValue}" },
+ // { typeof(IList), propValue => $"{propValue}" },
+ //};
+
+ // private static string GetPropertyRenderAttribute(PropertyInfo prop)
+ // {
+ // var propValue = prop.PropertyType.IsValueType ? $"{GetIdentifierName(prop.Name)}.Value" : GetIdentifierName(prop.Name);
+ // var formattedValue = propValue;
+ // if (TypeToAttributeHelperGetter.TryGetValue(prop.PropertyType, out var formattingFunc))
+ // {
+ // formattedValue = formattingFunc(propValue);
+ // }
+ // else if (prop.PropertyType.IsEnum)
+ // {
+ // formattedValue = $"(int){formattedValue}";
+ // }
+ // else
+ // {
+ // // TODO: Error?
+ // Console.WriteLine($"WARNING: Couldn't generate attribute render for {prop.DeclaringType.Name}.{prop.Name}");
+ // }
+
+ // return $@" if ({GetIdentifierName(prop.Name)} != null)
+ // {{
+ // builder.AddAttribute(nameof({GetIdentifierName(prop.Name)}), {formattedValue});
+ // }}
+ //";
+ // }
+
+ private static readonly Dictionary TypeToCSharpName = new Dictionary
+ {
+ { typeof(bool), "bool" },
+ { typeof(byte), "byte" },
+ { typeof(sbyte), "sbyte" },
+ { typeof(char), "char" },
+ { typeof(decimal), "decimal" },
+ { typeof(double), "double" },
+ { typeof(float), "float" },
+ { typeof(int), "int" },
+ { typeof(uint), "uint" },
+ { typeof(long), "long" },
+ { typeof(ulong), "ulong" },
+ { typeof(object), "object" },
+ { typeof(short), "short" },
+ { typeof(ushort), "ushort" },
+ { typeof(string), "string" },
+ };
+
+ private static string GetCSharpType(Type propertyType)
+ {
+ return TypeToCSharpName.TryGetValue(propertyType, out var typeName) ? typeName : null;
+ }
+
+ /////
+ ///// Finds the next non-generic base type of the specified type. This matches the Mobile Blazor Bindings
+ ///// model where there is no need to represent the intermediate generic base classes because they are
+ ///// generally only containers and have no API functionality that needs to be generated.
+ /////
+ /////
+ /////
+ //private static Type GetBaseTypeOfInterest(Type type)
+ //{
+ // do
+ // {
+ // type = type.BaseType;
+ // if (!type.IsGenericType)
+ // {
+ // return type;
+ // }
+ // }
+ // while (type != null);
+
+ // return null;
+ //}
+
+ // private void GenerateHandlerFile(Type typeToGenerate, IEnumerable propertiesToGenerate, string outputFolder)
+ // {
+ // var fileName = Path.Combine(outputFolder, "Handlers", $"{typeToGenerate.Name}Handler.generated.cs");
+ // var directoryName = Path.GetDirectoryName(fileName);
+ // if (!string.IsNullOrEmpty(directoryName))
+ // {
+ // Directory.CreateDirectory(directoryName);
+ // }
+
+ // Console.WriteLine($"Generating component handler for type '{typeToGenerate.FullName}' into file '{fileName}'.");
+
+ // var componentName = typeToGenerate.Name;
+ // var componentVarName = char.ToLowerInvariant(componentName[0]) + componentName.Substring(1);
+ // var componentHandlerName = $"{componentName}Handler";
+ // var componentBaseName = GetBaseTypeOfInterest(typeToGenerate).Name;
+ // var componentHandlerBaseName = $"{componentBaseName}Handler";
+
+ // // header
+ // var headerText = Settings.FileHeader;
+
+ // // usings
+ // var usings = new List
+ // {
+ // //new UsingStatement { Namespace = "Microsoft.AspNetCore.Components" }, // Typically needed only when there are event handlers for the EventArgs types
+ // new UsingStatement { Namespace = "Microsoft.MobileBlazorBindings.Core" },
+ // new UsingStatement { Namespace = "System" },
+ // new UsingStatement { Namespace = "Xamarin.Forms", Alias = "XF" }
+ // };
+
+ // //// props
+ // //var propertySettersBuilder = new StringBuilder();
+ // //foreach (var prop in propertiesToGenerate)
+ // //{
+ // // propertySettersBuilder.Append(GetPropertySetAttribute(prop, usings));
+ // //}
+ // //var propertySetters = propertySettersBuilder.ToString();
+
+ // var usingsText = string.Join(
+ // Environment.NewLine,
+ // usings
+ // .Distinct()
+ // .Where(u => u.Namespace != Settings.RootNamespace)
+ // .OrderBy(u => u.ComparableString)
+ // .Select(u => u.UsingText));
+
+ // var isComponentAbstract = typeToGenerate.IsAbstract;
+ // var classModifiers = string.Empty;
+ // if (isComponentAbstract)
+ // {
+ // classModifiers += "abstract ";
+ // }
+
+ // var applyAttributesMethod = string.Empty;
+ // // if (!string.IsNullOrEmpty(propertySetters))
+ // // {
+ // // applyAttributesMethod = $@"
+ // // public override void ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName)
+ // // {{
+ // // switch (attributeName)
+ // // {{
+ // //{propertySetters} default:
+ // // base.ApplyAttribute(attributeEventHandlerId, attributeName, attributeValue, attributeEventUpdatesAttributeName);
+ // // break;
+ // // }}
+ // // }}
+ // //";
+ // // }
+
+ // var outputBuilder = new StringBuilder();
+ // outputBuilder.Append($@"{headerText}
+ //{usingsText}
+
+ //namespace {Settings.RootNamespace}.Handlers
+ //{{
+ // public {classModifiers}partial class {componentHandlerName} : {componentHandlerBaseName}
+ // {{
+ // public {componentName}Handler(NativeComponentRenderer renderer, XF.{componentName} {componentVarName}Control) : base(renderer, {componentVarName}Control)
+ // {{
+ // {componentName}Control = {componentVarName}Control ?? throw new ArgumentNullException(nameof({componentVarName}Control));
+
+ // Initialize(renderer);
+ // }}
+
+ // partial void Initialize(NativeComponentRenderer renderer);
+
+ // public XF.{componentName} {componentName}Control {{ get; }}
+ //{applyAttributesMethod} }}
+ //}}
+ //");
+
+ // File.WriteAllText(fileName, outputBuilder.ToString());
+ // }
+
+ // private static string GetPropertySetAttribute(PropertyInfo prop, List usings)
+ // {
+ // // Handle null values by resetting to default value
+ // var resetValueParameterExpression = string.Empty;
+ // var bindablePropertyForProp = GetBindablePropertyForProp(prop);
+ // if (bindablePropertyForProp != null)
+ // {
+ // var declaredDefaultValue = bindablePropertyForProp.DefaultValue;
+ // var defaultValueForType = GetDefaultValueForType(prop.PropertyType);
+ // var needsCustomResetValue = declaredDefaultValue == null ? false : !declaredDefaultValue.Equals(defaultValueForType);
+
+ // if (needsCustomResetValue)
+ // {
+ // var valueExpression = GetValueExpression(declaredDefaultValue, usings);
+ // if (string.IsNullOrEmpty(valueExpression))
+ // {
+ // Console.WriteLine($"WARNING: Couldn't get value expression for {prop.DeclaringType.Name}.{prop.Name} of type {prop.PropertyType.FullName}.");
+ // }
+ // resetValueParameterExpression = valueExpression;
+ // }
+ // }
+
+ // var formattedValue = string.Empty;
+ // if (TypeToAttributeHelperSetter.TryGetValue(prop.PropertyType, out var propValueFormat))
+ // {
+ // var resetValueParameterExpressionAsExtraParameter = string.Empty;
+ // if (!string.IsNullOrEmpty(resetValueParameterExpression))
+ // {
+ // resetValueParameterExpressionAsExtraParameter = ", " + resetValueParameterExpression;
+ // }
+ // formattedValue = string.Format(CultureInfo.InvariantCulture, propValueFormat, resetValueParameterExpressionAsExtraParameter);
+ // }
+ // else if (prop.PropertyType.IsEnum)
+ // {
+ // var resetValueParameterExpressionAsExtraParameter = string.Empty;
+ // if (!string.IsNullOrEmpty(resetValueParameterExpression))
+ // {
+ // resetValueParameterExpressionAsExtraParameter = ", (int)" + resetValueParameterExpression;
+ // }
+ // var castTypeName = GetTypeNameAndAddNamespace(prop.PropertyType, usings);
+ // formattedValue = $"({castTypeName})AttributeHelper.GetInt(attributeValue{resetValueParameterExpressionAsExtraParameter})";
+ // }
+ // else if (prop.PropertyType == typeof(string))
+ // {
+ // formattedValue =
+ // string.IsNullOrEmpty(resetValueParameterExpression)
+ // ? "(string)attributeValue"
+ // : string.Format(CultureInfo.InvariantCulture, "(string)attributeValue ?? {0}", resetValueParameterExpression);
+ // }
+ // else
+ // {
+ // // TODO: Error?
+ // Console.WriteLine($"WARNING: Couldn't generate property set for {prop.DeclaringType.Name}.{prop.Name}");
+ // }
+
+ // return $@" case nameof(XF.{prop.DeclaringType.Name}.{GetIdentifierName(prop.Name)}):
+ // {prop.DeclaringType.Name}Control.{GetIdentifierName(prop.Name)} = {formattedValue};
+ // break;
+ //";
+ // }
+
+ //private static string GetValueExpression(object declaredDefaultValue, List usings)
+ //{
+ // if (declaredDefaultValue is null)
+ // {
+ // throw new ArgumentNullException(nameof(declaredDefaultValue));
+ // }
+
+ // return declaredDefaultValue switch
+ // {
+ // bool boolValue => boolValue ? "true" : "false",
+ // int intValue => GetIntValueExpression(intValue),
+ // float floatValue => floatValue.ToString("F", CultureInfo.InvariantCulture) + "f", // "Fixed-Point": https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#the-fixed-point-f-format-specifier
+ // double doubleValue => doubleValue.ToString("F", CultureInfo.InvariantCulture), // "Fixed-Point": https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#the-fixed-point-f-format-specifier
+ // Enum enumValue => GetTypeNameAndAddNamespace(enumValue.GetType(), usings) + "." + Enum.GetName(enumValue.GetType(), declaredDefaultValue),
+ // XF.LayoutOptions layoutOptionsValue => GetLayoutOptionsValueExpression(layoutOptionsValue),
+ // string stringValue => $@"""{stringValue}""",
+ // // TODO: More types here
+ // _ => null,
+ // };
+ //}
+
+ //private static string GetLayoutOptionsValueExpression(XF.LayoutOptions layoutOptionsValue)
+ //{
+ // var expandSuffix = layoutOptionsValue.Expands ? "AndExpand" : string.Empty;
+ // return $"XF.LayoutOptions.{layoutOptionsValue.Alignment}{expandSuffix}";
+ //}
+
+ //private static string GetIntValueExpression(int intValue)
+ //{
+ // return intValue switch
+ // {
+ // int.MinValue => "int.MinValue",
+ // int.MaxValue => "int.MaxValue",
+ // _ => intValue.ToString(CultureInfo.InvariantCulture),
+ // };
+ //}
+
+ //private static object GetDefaultValueForType(Type propertyType)
+ //{
+ // if (propertyType.IsValueType)
+ // {
+ // return Activator.CreateInstance(propertyType);
+ // }
+ // return null;
+ //}
+
+ //private static XF.BindableProperty GetBindablePropertyForProp(PropertyInfo prop)
+ //{
+ // var bindablePropertyField = prop.DeclaringType.GetField(prop.Name + "Property");
+ // if (bindablePropertyField == null)
+ // {
+ // return null;
+ // }
+ // return (XF.BindableProperty)bindablePropertyField.GetValue(null);
+ //}
+
+ //private static readonly Dictionary TypeToAttributeHelperSetter = new Dictionary
+ //{
+ // { typeof(XF.Color), "AttributeHelper.StringToColor((string)attributeValue{0})" },
+ // { typeof(XF.CornerRadius), "AttributeHelper.StringToCornerRadius(attributeValue{0})" },
+ // { typeof(XF.ImageSource), "AttributeHelper.StringToImageSource(attributeValue{0})" },
+ // { typeof(XF.LayoutOptions), "AttributeHelper.StringToLayoutOptions(attributeValue{0})" },
+ // { typeof(XF.Thickness), "AttributeHelper.StringToThickness(attributeValue{0})" },
+ // { typeof(bool), "AttributeHelper.GetBool(attributeValue{0})" },
+ // { typeof(double), "AttributeHelper.StringToDouble((string)attributeValue{0})" },
+ // { typeof(float), "AttributeHelper.StringToSingle((string)attributeValue{0})" },
+ // { typeof(int), "AttributeHelper.GetInt(attributeValue{0})" },
+ // { typeof(IList), "AttributeHelper.GetStringList(attributeValue)" },
+ //};
+
+ static HashSet DisallowedPropertyName = new HashSet
+ {
+ "Site"
+ };
+
+ private static IEnumerable GetPropertiesToGenerate(Type componentType)
+ {
+ var allPublicProperties = componentType.GetProperties();
+
+ return
+ allPublicProperties
+ .Where(HasPublicGetAndSet)
+ .Where(prop => componentType == typeof(CPF.UIElement) || (componentType != typeof(CPF.UIElement) && prop.DeclaringType != typeof(CPF.UIElement) && prop.DeclaringType != typeof(CPF.Visual) && prop.DeclaringType != typeof(CPF.CpfObject)))
+ //.Where(prop => !DisallowedComponentPropertyTypes.Contains(prop.PropertyType))
+ .Where(prop => !DisallowedPropertyName.Contains(prop.Name))
+ .Where(IsPropertyBrowsable)
+ .OrderBy(prop => prop.Name, StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ }
+
+ private static bool HasPublicGetAndSet(PropertyInfo propInfo)
+ {
+ if (propInfo.PropertyType == typeof(CPF.UIElementTemplate) || propInfo.PropertyType.IsGenericType && propInfo.PropertyType.GetGenericTypeDefinition() == typeof(CPF.UIElementTemplate<>))
+ {
+ return false;
+ }
+ return propInfo.GetGetMethod() != null && propInfo.GetSetMethod() != null && propInfo.GetCustomAttribute(typeof(CPF.NotCpfProperty)) == null;
+ }
+
+ private static bool IsPropertyBrowsable(PropertyInfo propInfo)
+ {
+ // [EditorBrowsable(EditorBrowsableState.Never)]
+ var attr = (EditorBrowsableAttribute)Attribute.GetCustomAttribute(propInfo, typeof(EditorBrowsableAttribute));
+ return (attr == null) || (attr.State != EditorBrowsableState.Never);
+ }
+
+ private static string GetIdentifierName(string possibleIdentifier)
+ {
+ return ReservedKeywords.Contains(possibleIdentifier, StringComparer.Ordinal)
+ ? $"@{possibleIdentifier}"
+ : possibleIdentifier;
+ }
+
+ private static readonly List ReservedKeywords = new List
+ { "class", };
+ }
+}
diff --git a/CpfRazorSample/ComponentWrapperGenerator/GeneratorSettings.cs b/CpfRazorSample/ComponentWrapperGenerator/GeneratorSettings.cs
new file mode 100644
index 0000000..fe61f62
--- /dev/null
+++ b/CpfRazorSample/ComponentWrapperGenerator/GeneratorSettings.cs
@@ -0,0 +1,8 @@
+namespace ComponentWrapperGenerator
+{
+ public class GeneratorSettings
+ {
+ public string FileHeader { get; set; }
+ public string RootNamespace { get; set; }
+ }
+}
diff --git a/CpfRazorSample/ComponentWrapperGenerator/UsingStatement.cs b/CpfRazorSample/ComponentWrapperGenerator/UsingStatement.cs
new file mode 100644
index 0000000..eb78a32
--- /dev/null
+++ b/CpfRazorSample/ComponentWrapperGenerator/UsingStatement.cs
@@ -0,0 +1,12 @@
+namespace ComponentWrapperGenerator
+{
+ internal sealed class UsingStatement
+ {
+ public string Alias { get; set; }
+ public string Namespace { get; set; }
+
+ public string ComparableString => Alias?.ToUpperInvariant() ?? Namespace?.ToUpperInvariant();
+
+ public string UsingText => $"using {(Alias != null ? Alias + " = " : "")}{Namespace};";
+ }
+}
diff --git a/CpfRazorSample/CpfRazorSample.csproj b/CpfRazorSample/CpfRazorSample.csproj
index f7ea705..9ca6176 100644
--- a/CpfRazorSample/CpfRazorSample.csproj
+++ b/CpfRazorSample/CpfRazorSample.csproj
@@ -24,8 +24,8 @@
-
-
+
diff --git a/CpfRazorSample/Program.cs b/CpfRazorSample/Program.cs
index 5786464..9c8d4b2 100644
--- a/CpfRazorSample/Program.cs
+++ b/CpfRazorSample/Program.cs
@@ -4,6 +4,7 @@ using CPF.Windows;
using Microsoft.Extensions.Hosting;
using System;
using CPF.Razor;
+using ComponentWrapperGenerator;
namespace CpfRazorSample
{
@@ -14,8 +15,8 @@ namespace CpfRazorSample
{
Application.Initialize(
(OperatingSystemType.Windows, new WindowsPlatform(), new SkiaDrawingFactory())
- , (OperatingSystemType.OSX, new CPF.Mac.MacPlatform(), new SkiaDrawingFactory())//如果需要支持Mac才需要
- , (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory())//如果需要支持Linux才需要
+ //, (OperatingSystemType.OSX, new CPF.Mac.MacPlatform(), new SkiaDrawingFactory())//如果需要支持Mac才需要
+ //, (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory())//如果需要支持Linux才需要
);
var host = Host.CreateDefaultBuilder()
@@ -26,9 +27,46 @@ namespace CpfRazorSample
})
.Build();
- var window = new CPF.Controls.Window();
+ var window = new CPF.Controls.Window { Width = 500, Height = 500, Background = null };
host.AddComponent(window);
Application.Run(window);
+
+
+ }
+
+ static void Create()
+ {
+ var settings = new GeneratorSettings
+ {
+ FileHeader = @"//CPF自动生成.
+ ",
+ RootNamespace = "CPF.Razor.Controls",
+ };
+
+ var type = typeof(CPF.UIElement);
+ var viewType = typeof(CPF.Controls.View);
+ var types = type.Assembly.GetTypes();
+ CpfGenerateWrapperForType(type, settings, "");
+ //CpfGenerateWrapperForType(typeof(CPF.Controls.WindowFrame), settings, "");
+ foreach (var item in types)
+ {
+ if (item.IsPublic && item.IsSubclassOf(type) && !item.IsAbstract && !item.IsGenericType && !item.IsSubclassOf(viewType) && item.GetConstructor(Array.Empty()) != null)
+ {
+ var brow = item.GetCustomAttributes(typeof(System.ComponentModel.BrowsableAttribute), true);
+ if (brow != null && brow.Length > 0 && !(brow[0] as System.ComponentModel.BrowsableAttribute).Browsable)
+ {
+ continue;
+ }
+ CpfGenerateWrapperForType(item, settings, "");
+ }
+ }
+ }
+
+ private static void CpfGenerateWrapperForType(Type typeToGenerate, GeneratorSettings settings, string outputFolder)
+ {
+ var generator = new CpfComponentWrapperGenerator(settings);
+ generator.GenerateComponentWrapper(typeToGenerate, outputFolder);
+ Console.WriteLine();
}
}
}
diff --git a/CpfRazorSample/Test.razor b/CpfRazorSample/Test.razor
index fa2957e..3589f3f 100644
--- a/CpfRazorSample/Test.razor
+++ b/CpfRazorSample/Test.razor
@@ -1,18 +1,22 @@
-
-
-
-
- @if (visible)
- {
-
- }
-
+
+
+
+
+ @if (visible)
+ {
+
+ }
+
+
+
+
+
@code
{
bool visible = false;
string text = "test";
- void OnMouseDown()
+ void OnMouseDown(CPF.Input.MouseButtonEventArgs e)
{
text = "test" + visible;
visible = !visible;