CPF/CPF.Razor/Controls/Element.cs

186 lines
6.9 KiB
C#
Raw Normal View History

2024-01-08 17:37:26 +08:00
using CPF.Input;
using Microsoft.AspNetCore.Components;
2024-01-08 10:55:10 +08:00
//using Microsoft.MobileBlazorBindings.Core;
using System;
using System.Collections.Generic;
using System.Text;
2024-01-09 16:57:27 +08:00
using System.Reflection;
using CPF.Reflection;
using System.Threading.Tasks;
2024-01-08 10:55:10 +08:00
namespace CPF.Razor.Controls
{
2024-01-08 20:55:43 +08:00
public abstract partial class Element<T> : NativeControlComponentBase<T> where T : UIElement, new()
2024-01-08 10:55:10 +08:00
{
2024-01-09 16:57:27 +08:00
public Element()
{
type = GetType();
}
Type type;
2024-01-08 10:55:10 +08:00
protected override void RenderAttributes(AttributesBuilder builder)
{
base.RenderAttributes(builder);
2024-01-09 16:57:27 +08:00
//var type = GetType();
2024-01-08 17:37:26 +08:00
var ps = type.GetProperties();
foreach (var item in ps)
2024-01-08 10:55:10 +08:00
{
2024-01-08 17:37:26 +08:00
var attr = item.GetCustomAttributes(typeof(ParameterAttribute), true);
if (attr != null && attr.Length > 0 && item.PropertyType != typeof(RenderFragment))
{
var v = item.GetValue(this);
if (v != null)
{
if (item.PropertyType == typeof(EventCallback) || (item.PropertyType.IsGenericType && item.PropertyType.GetGenericTypeDefinition() == typeof(EventCallback<>)))
{//事件注册还必须加小写的on
2024-01-09 16:57:27 +08:00
if (cPs.ContainsKey(item.Name))
{
builder.AddAttribute("on" + item.Name, EventCallback.Factory.Create<ChangeEventArgs>(this, a => HandleChanged(item, a)));
}
else
{
builder.AddAttribute("on" + item.Name, v);
}
2024-01-08 17:37:26 +08:00
}
else
{
builder.AddAttribute(item.Name, v);
}
}
}
2024-01-08 10:55:10 +08:00
}
2024-01-08 17:37:26 +08:00
//if (MarginLeft != null)
//{
// builder.AddAttribute(nameof(MarginLeft), MarginLeft);
//}
}
2024-01-09 16:57:27 +08:00
private Task HandleChanged(PropertyInfo info, ChangeEventArgs evt)
{
return (Task)info.FastGetValue(this).Invoke("InvokeAsync", evt.Value);
}
2024-01-08 17:37:26 +08:00
public override void ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName)
{
2024-01-09 16:57:27 +08:00
//var p = Element.GetPropertyMetadata(attributeName);
//var p = Element.Type.GetProperty(attributeName);
//if (p != null)
if (ePs.TryGetValue(attributeName, out var p))
2024-01-08 10:55:10 +08:00
{
2024-01-09 16:57:27 +08:00
//Element.SetValue(attributeValue.ConvertTo(p.PropertyType), attributeName);
//p.FastSetValue(Element, attributeValue.ConvertTo(p.PropertyType));
//这边传过来的值会变成字符串,那直接读取这边的属性值就好了
var value = this.GetValue(attributeName);
p.FastSetValue(Element, value.ConvertTo(p.PropertyType));
2024-01-08 10:55:10 +08:00
}
2024-01-08 17:37:26 +08:00
else
2024-01-08 10:55:10 +08:00
{
2024-01-08 17:37:26 +08:00
if (events.Contains(attributeName))
{
handlerIds[attributeName] = attributeEventHandlerId;
Renderer.RegisterEvent(attributeEventHandlerId, id => { if (id == attributeEventHandlerId) { handlerIds.Remove(attributeName); } });
}
2024-01-08 10:55:10 +08:00
}
2024-01-08 17:37:26 +08:00
}
Dictionary<string, ulong> handlerIds = new Dictionary<string, ulong>();
HashSet<string> events = new HashSet<string>();
2024-01-09 16:57:27 +08:00
/// <summary>
/// 元素属性
/// </summary>
Dictionary<string, System.Reflection.PropertyInfo> ePs = new Dictionary<string, System.Reflection.PropertyInfo>();
/// <summary>
/// 依赖属性用于绑定通知TextChanged
/// </summary>
Dictionary<string, System.Reflection.PropertyInfo> cPs = new Dictionary<string, System.Reflection.PropertyInfo>();
2024-01-08 17:37:26 +08:00
protected override T CreateElement()
{
var r = base.CreateElement();
var type = typeof(T);
2024-01-09 16:57:27 +08:00
var es = type.GetEvents();
var ps = type.GetProperties();
2024-01-08 17:37:26 +08:00
foreach (var item in ps)
2024-01-08 10:55:10 +08:00
{
2024-01-09 16:57:27 +08:00
if (item.Name != "Item" || item.GetIndexParameters().Length == 0)
{
ePs.Add(item.Name, item);
if (r.GetPropertyMetadata(item.Name) != null)
{
cPs.Add(item.Name + "Changed", item);
}
}
}
foreach (var item in es)
{
if (cPs.ContainsKey(item.Name))
{//过滤CPF内置的相同名称事件
continue;
}
2024-01-08 17:37:26 +08:00
var name = "on" + item.Name;
events.Add(name);
r.Commands.Add(item.Name, (s, e) =>
{
if (handlerIds.TryGetValue(name, out var id))
{
Renderer.Dispatcher.InvokeAsync(() => Renderer.DispatchEventAsync(id, null, e as EventArgs));
}
});
2024-01-08 10:55:10 +08:00
}
2024-01-09 16:57:27 +08:00
foreach (var item in cPs)
{
var name = "on" + item.Key;
events.Add(name);
}
r.Commands.Add(nameof(r.PropertyChanged), (s, e) =>
{
var pe = (CPFPropertyChangedEventArgs)e;
if (handlerIds.TryGetValue("on" + pe.PropertyName + "Changed", out var id))
{
var newValue = pe.NewValue;
Renderer.Dispatcher.InvokeAsync(() =>
{
if (!handlerIds.ContainsValue(id))
{
return Task.CompletedTask;
}
return Renderer.DispatchEventAsync(id, null, new ChangeEventArgs { Value = newValue });
});
}
});
2024-01-08 17:37:26 +08:00
return r;
2024-01-08 10:55:10 +08:00
}
2024-01-08 17:37:26 +08:00
2024-01-09 00:39:58 +08:00
public void HandleText(int index, string text)
{
if (Element is CPF.Controls.ContentControl control)
{
control.Content = text;
}
}
2024-01-08 17:37:26 +08:00
2024-01-09 16:57:27 +08:00
public static implicit operator T(Element<T> element)
{
return element.Element;
}
2024-01-08 20:55:43 +08:00
////只要属性和事件自动生成就行
//[Parameter] public string Name { get; set; }
//[Parameter] public FloatField? MarginLeft { get; set; }
//[Parameter] public FloatField? MarginTop { get; set; }
//[Parameter] public FloatField? MarginBottom { get; set; }
//[Parameter] public FloatField? MarginRight { get; set; }
//[Parameter] public CPF.FloatField? Width { get; set; }
//[Parameter] public CPF.FloatField? Height { get; set; }
//[Parameter] public EventCallback<MouseButtonEventArgs> MouseDown { get; set; }
2024-01-08 17:37:26 +08:00
2024-01-08 10:55:10 +08:00
}
2024-01-09 16:57:27 +08:00
2024-01-08 10:55:10 +08:00
}