Merge branch 'master' into Toolkit
This commit is contained in:
commit
6631fec5e6
@ -657,6 +657,7 @@ namespace CPF.Windows
|
|||||||
WM_USER = 0x0400,
|
WM_USER = 0x0400,
|
||||||
WM_DISPATCH_WORK_ITEM = WM_USER,
|
WM_DISPATCH_WORK_ITEM = WM_USER,
|
||||||
WM_TOUCH = 0x0240,
|
WM_TOUCH = 0x0240,
|
||||||
|
WM_GESTURE = 0x0119,
|
||||||
//WM_PARENTNOTIFY = 0x0210,
|
//WM_PARENTNOTIFY = 0x0210,
|
||||||
WM_NCPOINTERUPDATE = 0x0241,
|
WM_NCPOINTERUPDATE = 0x0241,
|
||||||
WM_NCPOINTERDOWN = 0x0242,
|
WM_NCPOINTERDOWN = 0x0242,
|
||||||
|
@ -74,6 +74,7 @@ namespace CPF.Windows
|
|||||||
}
|
}
|
||||||
|
|
||||||
WNDCLASSEX wc = new WNDCLASSEX();
|
WNDCLASSEX wc = new WNDCLASSEX();
|
||||||
|
bool touchMsg;
|
||||||
public WindowImpl()
|
public WindowImpl()
|
||||||
{
|
{
|
||||||
if (Window == null)
|
if (Window == null)
|
||||||
@ -89,6 +90,10 @@ namespace CPF.Windows
|
|||||||
{
|
{
|
||||||
isLayered = true;
|
isLayered = true;
|
||||||
}
|
}
|
||||||
|
if ((v.Major == 6 && v.Minor < 2))
|
||||||
|
{
|
||||||
|
touchMsg = RegisterTouchWindow(handle, RegisterTouchFlags.TWF_NONE);
|
||||||
|
}
|
||||||
_className = "CPFWindow-" + Guid.NewGuid();
|
_className = "CPFWindow-" + Guid.NewGuid();
|
||||||
// 初始化窗口类结构
|
// 初始化窗口类结构
|
||||||
wc.cbSize = Marshal.SizeOf(typeof(WNDCLASSEX));
|
wc.cbSize = Marshal.SizeOf(typeof(WNDCLASSEX));
|
||||||
@ -707,60 +712,83 @@ namespace CPF.Windows
|
|||||||
case WindowsMessage.WM_POINTERDOWN:
|
case WindowsMessage.WM_POINTERDOWN:
|
||||||
case WindowsMessage.WM_POINTERUP:
|
case WindowsMessage.WM_POINTERUP:
|
||||||
case WindowsMessage.WM_POINTERUPDATE:
|
case WindowsMessage.WM_POINTERUPDATE:
|
||||||
var id = GetPointerId(wParam);
|
if (!touchMsg)
|
||||||
var position = GetPointerLocation(lParam);
|
|
||||||
position = PointToClient(position);
|
|
||||||
//Debug.WriteLine("id:" + id + " " + position);
|
|
||||||
POINTER_INFO pi = new POINTER_INFO();
|
|
||||||
if (GetPointerInfo(id, ref pi))
|
|
||||||
{
|
{
|
||||||
switch ((WindowsMessage)msg)
|
var id = GetPointerId(wParam);
|
||||||
|
var position = GetPointerLocation(lParam);
|
||||||
|
position = PointToClient(position);
|
||||||
|
//Debug.WriteLine("id:" + id + " " + position);
|
||||||
|
POINTER_INFO pi = new POINTER_INFO();
|
||||||
|
if (GetPointerInfo(id, ref pi))
|
||||||
{
|
{
|
||||||
case WindowsMessage.WM_POINTERDOWN:
|
switch ((WindowsMessage)msg)
|
||||||
//Debug.WriteLine("down");
|
{
|
||||||
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchDown);
|
case WindowsMessage.WM_POINTERDOWN:
|
||||||
break;
|
//Debug.WriteLine("down");
|
||||||
case WindowsMessage.WM_POINTERUP:
|
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchDown);
|
||||||
//Debug.WriteLine("up");
|
break;
|
||||||
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchUp);
|
case WindowsMessage.WM_POINTERUP:
|
||||||
//root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchLeave);
|
//Debug.WriteLine("up");
|
||||||
break;
|
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchUp);
|
||||||
case WindowsMessage.WM_POINTERUPDATE:
|
//root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchLeave);
|
||||||
//Debug.WriteLine("update");
|
break;
|
||||||
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchMove);
|
case WindowsMessage.WM_POINTERUPDATE:
|
||||||
break;
|
//Debug.WriteLine("update");
|
||||||
|
root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint { Id = id, Position = position }, root.InputManager.TouchDevice, Root), root.LayoutManager.VisibleUIElements, EventType.TouchMove);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WindowsMessage.WM_POINTERWHEEL:
|
case WindowsMessage.WM_POINTERWHEEL:
|
||||||
Debug.WriteLine("WM_POINTERWHEEL");
|
Debug.WriteLine("WM_POINTERWHEEL");
|
||||||
break;
|
break;
|
||||||
//case WindowsMessage.WM_TOUCH:
|
case WindowsMessage.WM_GESTURE:
|
||||||
// {
|
Debug.WriteLine("WM_GESTURE");
|
||||||
// var touchInputCount = wParam.ToInt32();
|
break;
|
||||||
// var pTouchInputs = stackalloc TOUCHINPUT[touchInputCount];
|
case WindowsMessage.WM_TOUCH:
|
||||||
// if (GetTouchInputInfo(lParam, (uint)touchInputCount, pTouchInputs, Marshal.SizeOf(typeof(TOUCHINPUT))))
|
if (touchMsg)
|
||||||
// {
|
{
|
||||||
// for (int i = 0; i < touchInputCount; i++)
|
var touchInputCount = wParam.ToInt32();
|
||||||
// {
|
var pTouchInputs = stackalloc TOUCHINPUT[touchInputCount];
|
||||||
// var touchInput = pTouchInputs[i];
|
if (GetTouchInputInfo(lParam, (uint)touchInputCount, pTouchInputs, Marshal.SizeOf(typeof(TOUCHINPUT))))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < touchInputCount; i++)
|
||||||
|
{
|
||||||
|
var input = pTouchInputs[i];
|
||||||
|
|
||||||
// //Input?.Invoke(new RawTouchEventArgs(_touchDevice, touchInput.Time,
|
if ((input.Flags & TouchInputFlags.TOUCHEVENTF_DOWN) > 0)
|
||||||
// // _owner,
|
{
|
||||||
// // touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_UP) ?
|
Root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint
|
||||||
// // RawPointerEventType.TouchEnd :
|
{
|
||||||
// // touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_DOWN) ?
|
Id = (int)input.Id,
|
||||||
// // RawPointerEventType.TouchBegin :
|
Position = new Point((float)(input.X * 0.01), (float)(input.Y * 0.01))
|
||||||
// // RawPointerEventType.TouchUpdate,
|
}, Root.InputManager.TouchDevice, Root), Root.LayoutManager.VisibleUIElements, EventType.TouchDown);
|
||||||
// // PointToClient(new PixelPoint(touchInput.X / 100, touchInput.Y / 100)),
|
|
||||||
// // WindowsKeyboardDevice.Instance.Modifiers,
|
}
|
||||||
// // touchInput.Id));
|
else if ((input.Flags & TouchInputFlags.TOUCHEVENTF_UP) > 0)
|
||||||
// }
|
{
|
||||||
// CloseTouchInputHandle(lParam);
|
Root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint
|
||||||
// return IntPtr.Zero;
|
{
|
||||||
// }
|
Id = (int)input.Id,
|
||||||
// break;
|
Position = new Point((float)(input.X * 0.01), (float)(input.Y * 0.01))
|
||||||
// }
|
}, Root.InputManager.TouchDevice, Root), Root.LayoutManager.VisibleUIElements, EventType.TouchUp);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ((input.Flags & TouchInputFlags.TOUCHEVENTF_MOVE) > 0)
|
||||||
|
{
|
||||||
|
Root.InputManager.TouchDevice.ProcessEvent(new TouchEventArgs(new TouchPoint
|
||||||
|
{
|
||||||
|
Id = (int)input.Id,
|
||||||
|
Position = new Point((float)(input.X * 0.01), (float)(input.Y * 0.01))
|
||||||
|
}, Root.InputManager.TouchDevice, Root), Root.LayoutManager.VisibleUIElements, EventType.TouchMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseTouchInputHandle(lParam);
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case UnmanagedMethods.WindowsMessage.WM_CLOSE:
|
case UnmanagedMethods.WindowsMessage.WM_CLOSE:
|
||||||
bool? preventClosing = Closing?.Invoke();
|
bool? preventClosing = Closing?.Invoke();
|
||||||
if (preventClosing == true)
|
if (preventClosing == true)
|
||||||
@ -1523,7 +1551,7 @@ namespace CPF.Windows
|
|||||||
}
|
}
|
||||||
invalidateRect.Intersect(all);//最后失效区域为在控件区域里面的相交区域
|
invalidateRect.Intersect(all);//最后失效区域为在控件区域里面的相交区域
|
||||||
}
|
}
|
||||||
if (!paint && (timer == null ))//&& isLayered
|
if (!paint && (timer == null))//&& isLayered
|
||||||
{
|
{
|
||||||
paint = true;
|
paint = true;
|
||||||
BeginInvoke(a =>
|
BeginInvoke(a =>
|
||||||
@ -1692,7 +1720,6 @@ namespace CPF.Windows
|
|||||||
public void SetVisible(bool visible)
|
public void SetVisible(bool visible)
|
||||||
{
|
{
|
||||||
//var v = IsWindowVisible(handle);
|
//var v = IsWindowVisible(handle);
|
||||||
root.InputManager.TouchDevice.ClearPoints();
|
|
||||||
if (visible)
|
if (visible)
|
||||||
{
|
{
|
||||||
if (windowState == WindowState.Normal)
|
if (windowState == WindowState.Normal)
|
||||||
|
@ -212,4 +212,104 @@ namespace CPF
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
public class AttachedDescribe : BindingDescribe
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
public AttachedDescribe(object value, string sourceProperty) : base(sourceProperty)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="binding"></param>
|
||||||
|
public AttachedDescribe(object value, string sourceProperty, BindingMode binding) : base(sourceProperty, binding)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="binding"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty, BindingMode binding) : base(source, sourceProperty, binding)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty) : base(source, sourceProperty)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="convert"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty, Func<object, object> convert) : base(source, sourceProperty, convert)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="binding"></param>
|
||||||
|
/// <param name="convert"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty, BindingMode binding, Func<object, object> convert) : base(source, sourceProperty, binding, convert)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="binding"></param>
|
||||||
|
/// <param name="convert"></param>
|
||||||
|
/// <param name="convertBack"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty, BindingMode binding, Func<object, object> convert, Func<object, object> convertBack) : base(source, sourceProperty, binding, convert, convertBack)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 设置和绑定附加属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="sourceProperty"></param>
|
||||||
|
/// <param name="binding"></param>
|
||||||
|
/// <param name="convert"></param>
|
||||||
|
/// <param name="convertBack"></param>
|
||||||
|
/// <param name="SourceToTargetError"></param>
|
||||||
|
/// <param name="TargetToSourceError"></param>
|
||||||
|
public AttachedDescribe(object value, object source, string sourceProperty, BindingMode binding, Func<object, object> convert, Func<object, object> convertBack, Action<Binding, object, Exception> SourceToTargetError, Action<Binding, object, Exception> TargetToSourceError) : base(source, sourceProperty, binding, convert, convertBack, SourceToTargetError, TargetToSourceError)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public object Value { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
130
CPF/Binding.cs
130
CPF/Binding.cs
@ -12,6 +12,7 @@ using System.Reflection.Emit;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -236,6 +237,14 @@ namespace CPF
|
|||||||
internal set;
|
internal set;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 链式绑定下标
|
||||||
|
/// </summary>
|
||||||
|
public int SourcePropertyIndex
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
} = 0;
|
||||||
|
/// <summary>
|
||||||
/// Owner被绑定的属性名
|
/// Owner被绑定的属性名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TargetPropertyName
|
public string TargetPropertyName
|
||||||
@ -353,6 +362,7 @@ namespace CPF
|
|||||||
current.Push(this);
|
current.Push(this);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Source == null || !Source.IsAlive)
|
if (Source == null || !Source.IsAlive)
|
||||||
{
|
{
|
||||||
if (Owner.HasProperty(TargetPropertyName))
|
if (Owner.HasProperty(TargetPropertyName))
|
||||||
@ -366,29 +376,22 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//CpfObject s = Source.Target as CpfObject;
|
/*var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
//if (s == null)
|
if (SourcePropertyNames.Length > 1) {
|
||||||
//{
|
value = Source.Target;
|
||||||
// var p = Source.Target.GetType().GetProperty(SourcePropertyName);
|
for (int i = 0; i < SourcePropertyNames.Length; i++)
|
||||||
// if (p == null)
|
{
|
||||||
// {
|
value = value.GetPropretyValue(SourcePropertyNames[i]);
|
||||||
// throw new Exception("未找到" + Source.Target + "的属性:" + SourcePropertyName);
|
}
|
||||||
// }
|
}
|
||||||
// value = p.FastGetValue(Source.Target);
|
else
|
||||||
//}
|
{
|
||||||
//else
|
value = Source.Target.GetPropretyValue(SourcePropertyName);
|
||||||
//{
|
}*/
|
||||||
// if (s.HasProperty(SourcePropertyName))
|
value = GetPropertySource(SourcePropertyName, Source.Target);
|
||||||
// {
|
if (value != null) {
|
||||||
// value = s.GetValue(SourcePropertyName);
|
value = value.GetPropretyValue(SourcePropertyName.Split('.').LastOrDefault());
|
||||||
// }
|
}
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// var p = s.Type.GetProperty(SourcePropertyName);
|
|
||||||
// value = p.FastGetValue(Source.Target);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
value = Source.Target.GetPropretyValue(SourcePropertyName);
|
|
||||||
if (Convert != null)
|
if (Convert != null)
|
||||||
{
|
{
|
||||||
value = Convert(value);
|
value = Convert(value);
|
||||||
@ -453,8 +456,23 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
if (!b.SetValue(nv, SourcePropertyName))
|
if (!b.SetValue(nv, SourcePropertyName))
|
||||||
{
|
{
|
||||||
|
/*var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
|
if (SourcePropertyNames.Length == 1)
|
||||||
|
{
|
||||||
|
b.SetValue(SourcePropertyName, nv);
|
||||||
|
}*/
|
||||||
|
/*var Target = b;
|
||||||
|
for (int i = 0; i < SourcePropertyNames.Length-1; i++)
|
||||||
|
{
|
||||||
|
Target = Target.GetPropretyValue(SourcePropertyNames[i]) as CpfObject;
|
||||||
|
}*/
|
||||||
|
var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
|
var Target = GetPropertySource(SourcePropertyName, b);
|
||||||
|
if (Target != null) {
|
||||||
|
Target.SetValue(SourcePropertyNames.LastOrDefault(), nv);
|
||||||
|
}
|
||||||
|
|
||||||
//b.Type.GetProperty(SourcePropertyName).FastSetValue(b, nv);
|
//b.Type.GetProperty(SourcePropertyName).FastSetValue(b, nv);
|
||||||
b.SetValue(SourcePropertyName, nv);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -533,7 +551,8 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (SourcePropertyName == e.PropertyName)
|
var Temp_SourcePropertyName = SourcePropertyName.Split('.').LastOrDefault();
|
||||||
|
if (Temp_SourcePropertyName == e.PropertyName)
|
||||||
{
|
{
|
||||||
//CPFObject s = sender as CPFObject;
|
//CPFObject s = sender as CPFObject;
|
||||||
//object value;
|
//object value;
|
||||||
@ -557,6 +576,47 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal object GetPropertySource(string SourcePropertyName,object Source)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
|
if (SourcePropertyNames.Length == 1)
|
||||||
|
{
|
||||||
|
return Source;
|
||||||
|
}
|
||||||
|
var Target = Source;
|
||||||
|
for (int i = 0; i < SourcePropertyNames.Length - 1; i++)
|
||||||
|
{
|
||||||
|
var Temp_Target = Target.GetPropretyValue(SourcePropertyNames[i]) as CpfObject;
|
||||||
|
if (Temp_Target == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Target = Temp_Target;
|
||||||
|
}
|
||||||
|
return Target;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception($"错误:{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpfObject SourceProperty = null;
|
||||||
|
private void Target_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
//重新绑定
|
||||||
|
if (BindingMode == BindingMode.TwoWay ||
|
||||||
|
BindingMode == BindingMode.OneWay ||
|
||||||
|
BindingMode == BindingMode.OneTime)
|
||||||
|
{
|
||||||
|
var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
|
var Temp_Target = GetPropertySource(SourcePropertyName, Source.Target);
|
||||||
|
var data = (Temp_Target as CpfObject)?.GetValue(SourcePropertyNames.LastOrDefault());
|
||||||
|
Owner.SetPropretyValue(TargetPropertyName, data);
|
||||||
|
}
|
||||||
|
RegisterPropertyChanged(sender as INotifyPropertyChanged);
|
||||||
|
}
|
||||||
|
|
||||||
internal void RegisterPropertyChanged(INotifyPropertyChanged notify)
|
internal void RegisterPropertyChanged(INotifyPropertyChanged notify)
|
||||||
{
|
{
|
||||||
@ -564,7 +624,25 @@ namespace CPF
|
|||||||
//{
|
//{
|
||||||
// throw new Exception("错误");
|
// throw new Exception("错误");
|
||||||
//}
|
//}
|
||||||
RegisterPropertyChanged(notify, PropertyChanged);
|
var SourcePropertyNames = SourcePropertyName.Split('.');
|
||||||
|
if (SourcePropertyNames.Length == 1)
|
||||||
|
{
|
||||||
|
RegisterPropertyChanged(notify, PropertyChanged);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var Target = Source.Target;
|
||||||
|
RegisterPropertyChanged(Target as CpfObject, Target_PropertyChanged);
|
||||||
|
for (int i = 0; i < SourcePropertyNames.Length - 1; i++)
|
||||||
|
{
|
||||||
|
var Temp_Target = Target.GetPropretyValue(SourcePropertyNames[i]) as CpfObject;
|
||||||
|
if (Temp_Target == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RegisterPropertyChanged(Temp_Target, Target_PropertyChanged);
|
||||||
|
Target = Temp_Target;
|
||||||
|
}
|
||||||
|
RegisterPropertyChanged(Target as INotifyPropertyChanged, PropertyChanged);
|
||||||
}
|
}
|
||||||
internal void CancellationPropertyChanged(INotifyPropertyChanged notify)
|
internal void CancellationPropertyChanged(INotifyPropertyChanged notify)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -16,6 +17,7 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
PropertyName = sourceProperty;
|
PropertyName = sourceProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindingDescribe(string sourceProperty, BindingMode binding)
|
public BindingDescribe(string sourceProperty, BindingMode binding)
|
||||||
{
|
{
|
||||||
PropertyName = sourceProperty;
|
PropertyName = sourceProperty;
|
||||||
@ -64,7 +66,7 @@ namespace CPF
|
|||||||
this.TargetToSourceError = TargetToSourceError;
|
this.TargetToSourceError = TargetToSourceError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindingDescribe(Action<CpfObject, object> command)
|
public BindingDescribe(CommandDescribe command)
|
||||||
{
|
{
|
||||||
Command = command;
|
Command = command;
|
||||||
}
|
}
|
||||||
@ -78,7 +80,7 @@ namespace CPF
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 简化绑定命令的命令,如果设置了该属性,则使用命令绑定
|
/// 简化绑定命令的命令,如果设置了该属性,则使用命令绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<CpfObject, object> Command { get; set; }
|
public CommandDescribe Command { get; set; }
|
||||||
|
|
||||||
//public CpfObject Owner { get; internal set; }
|
//public CpfObject Owner { get; internal set; }
|
||||||
|
|
||||||
@ -331,7 +333,14 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
//public static BindingDescribe operator *(BindingDescribe property1, string property2)
|
||||||
|
//{
|
||||||
|
// return null;
|
||||||
|
//}
|
||||||
|
//public static BindingDescribe operator *(BindingDescribe property1, BindingDescribe property2)
|
||||||
|
//{
|
||||||
|
// return null;
|
||||||
|
//}
|
||||||
public BindingMode BindingMode { get; set; } = BindingMode.OneWay;
|
public BindingMode BindingMode { get; set; } = BindingMode.OneWay;
|
||||||
public object Source { get; set; }
|
public object Source { get; set; }
|
||||||
|
|
||||||
@ -343,7 +352,7 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
return new BindingDescribe { PropertyName = sourceProperty };
|
return new BindingDescribe { PropertyName = sourceProperty };
|
||||||
}
|
}
|
||||||
public static explicit operator BindingDescribe(Action<CpfObject, object> command)
|
public static implicit operator BindingDescribe(CommandDescribe command)
|
||||||
{
|
{
|
||||||
return new BindingDescribe { Command = command };
|
return new BindingDescribe { Command = command };
|
||||||
}
|
}
|
||||||
@ -386,5 +395,50 @@ namespace CPF
|
|||||||
return base.GetHashCode();
|
return base.GetHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 命令绑定
|
||||||
|
/// </summary>
|
||||||
|
public class CommandDescribe
|
||||||
|
{
|
||||||
|
public Action<CpfObject, object> Action { get; set; }
|
||||||
|
|
||||||
|
public string MethodName { get; set; }
|
||||||
|
public object[] Parameters { get; set; }
|
||||||
|
|
||||||
|
public object Target { get; set; }
|
||||||
|
|
||||||
|
public Func<UIElement, UIElement> Find { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 用委托定义个命令绑定
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command"></param>
|
||||||
|
public CommandDescribe(Action<CpfObject, object> command)
|
||||||
|
{
|
||||||
|
Action = command;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 定义个命令绑定
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="methodName"></param>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <param name="ps"></param>
|
||||||
|
public CommandDescribe(string methodName, object obj = null, params object[] ps)
|
||||||
|
{
|
||||||
|
MethodName = methodName;
|
||||||
|
Parameters = ps;
|
||||||
|
Target = obj;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 查找元素并绑定命令
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="methodName"></param>
|
||||||
|
/// <param name="find"></param>
|
||||||
|
/// <param name="ps"></param>
|
||||||
|
public CommandDescribe(string methodName, Func<UIElement, UIElement> find, params object[] ps)
|
||||||
|
{
|
||||||
|
MethodName = methodName;
|
||||||
|
Parameters = ps;
|
||||||
|
Find = find;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using CPF.Controls;
|
using CPF.Controls;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -102,6 +103,7 @@ namespace CPF
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//((INotifyPropertyChanged)source).PropertyChanged += b.PropertyChanged;
|
//((INotifyPropertyChanged)source).PropertyChanged += b.PropertyChanged;
|
||||||
|
|
||||||
b.RegisterPropertyChanged((INotifyPropertyChanged)source);
|
b.RegisterPropertyChanged((INotifyPropertyChanged)source);
|
||||||
b.SourceToTarget();
|
b.SourceToTarget();
|
||||||
}
|
}
|
||||||
@ -114,6 +116,7 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
b.SourceToTarget();
|
b.SourceToTarget();
|
||||||
}
|
}
|
||||||
|
//Debug.WriteLine($"sourcePropertyName:{sourcePropertyName},bindingMode:{bindingMode}");
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -558,8 +558,9 @@ namespace CPF.Controls
|
|||||||
if (codeTextView.Text.Length >= caretIndex)
|
if (codeTextView.Text.Length >= caretIndex)
|
||||||
{
|
{
|
||||||
//Text = codeTextView.Text.Insert((int)caretIndex, e.Text);
|
//Text = codeTextView.Text.Insert((int)caretIndex, e.Text);
|
||||||
codeTextView.InsertText(caretIndex, e.Text);
|
var caretIndex_old = caretIndex;
|
||||||
caretIndex = caretIndex + (uint)e.Text.Length;
|
caretIndex = caretIndex + (uint)e.Text.Length;
|
||||||
|
codeTextView.InsertText(caretIndex_old, e.Text);
|
||||||
selectionEnd = caretIndex;
|
selectionEnd = caretIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -11,9 +11,11 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace CPF.Controls
|
namespace CPF.Controls
|
||||||
{
|
{
|
||||||
|
[Browsable(false)]
|
||||||
public class LineNumber : Control
|
public class LineNumber : Control
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -149,6 +149,25 @@ namespace CPF.Controls
|
|||||||
{
|
{
|
||||||
base.OnOverrideMetadata(overridePropertys);
|
base.OnOverrideMetadata(overridePropertys);
|
||||||
overridePropertys.Override(nameof(Height), new UIPropertyMetadataAttribute((FloatField)"100%", UIPropertyOptions.AffectsMeasure));
|
overridePropertys.Override(nameof(Height), new UIPropertyMetadataAttribute((FloatField)"100%", UIPropertyOptions.AffectsMeasure));
|
||||||
|
//overridePropertys.Override(nameof(DataContext), new UIPropertyMetadataAttribute(null, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//protected override void OnLayoutUpdated()
|
||||||
|
//{
|
||||||
|
// base.OnLayoutUpdated();
|
||||||
|
// if (Root.LayoutManager.IsVisible(this))
|
||||||
|
// {
|
||||||
|
// DataContext = Row.DataContext;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
||||||
|
//{
|
||||||
|
// if (propertyName == nameof(DataContext))
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,6 +282,7 @@ namespace CPF.Controls
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
textSize = new Size();
|
||||||
return base.ArrangeOverride(finalSize);
|
return base.ArrangeOverride(finalSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -860,6 +860,7 @@ namespace CPF.Controls
|
|||||||
base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
if (propertyName == nameof(Visibility))
|
if (propertyName == nameof(Visibility))
|
||||||
{
|
{
|
||||||
|
InputManager.TouchDevice.ClearPoints();
|
||||||
viewImpl.SetVisible((Visibility)newValue == Visibility.Visible);
|
viewImpl.SetVisible((Visibility)newValue == Visibility.Visible);
|
||||||
}
|
}
|
||||||
if (!onChecked && radioButtonGroupProperty != null && radiobuttons != null && radioButtonGroupProperty.TryGetValue(propertyName, out var group))
|
if (!onChecked && radioButtonGroupProperty != null && radiobuttons != null && radioButtonGroupProperty.TryGetValue(propertyName, out var group))
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,17 +25,20 @@ namespace CPF
|
|||||||
static ConcurrentDictionary<Type, ObjInfo> typeCache = new ConcurrentDictionary<Type, ObjInfo>();
|
static ConcurrentDictionary<Type, ObjInfo> typeCache = new ConcurrentDictionary<Type, ObjInfo>();
|
||||||
static ConcurrentDictionary<Type, PropertyMetadataAttribute[]> typePropertyCache = new ConcurrentDictionary<Type, PropertyMetadataAttribute[]>();
|
static ConcurrentDictionary<Type, PropertyMetadataAttribute[]> typePropertyCache = new ConcurrentDictionary<Type, PropertyMetadataAttribute[]>();
|
||||||
static ConcurrentDictionary<Type, HashSet<string>> inheritsProperties = new ConcurrentDictionary<Type, HashSet<string>>();
|
static ConcurrentDictionary<Type, HashSet<string>> inheritsProperties = new ConcurrentDictionary<Type, HashSet<string>>();
|
||||||
|
static ConcurrentDictionary<Type, HashSet<string>> breakInheritsProperties = new ConcurrentDictionary<Type, HashSet<string>>();
|
||||||
static ConcurrentDictionary<Type, List<MethodInfo>> propertyChangedMethods = new ConcurrentDictionary<Type, List<MethodInfo>>();
|
static ConcurrentDictionary<Type, List<MethodInfo>> propertyChangedMethods = new ConcurrentDictionary<Type, List<MethodInfo>>();
|
||||||
|
|
||||||
static KeyValuePair<Type, ObjInfo>[] saveTypeCache;
|
static KeyValuePair<Type, ObjInfo>[] saveTypeCache;
|
||||||
static KeyValuePair<Type, PropertyMetadataAttribute[]>[] saveTypePropertyCache;
|
static KeyValuePair<Type, PropertyMetadataAttribute[]>[] saveTypePropertyCache;
|
||||||
static KeyValuePair<Type, HashSet<string>>[] saveInheritsProperties;
|
static KeyValuePair<Type, HashSet<string>>[] saveInheritsProperties;
|
||||||
|
static KeyValuePair<Type, HashSet<string>>[] saveBreakInheritsProperties;
|
||||||
static KeyValuePair<Type, List<MethodInfo>>[] savePropertyChangedMethods;
|
static KeyValuePair<Type, List<MethodInfo>>[] savePropertyChangedMethods;
|
||||||
public static void SetTypeCache()
|
public static void SetTypeCache()
|
||||||
{
|
{
|
||||||
saveTypeCache = typeCache.ToArray();
|
saveTypeCache = typeCache.ToArray();
|
||||||
saveTypePropertyCache = typePropertyCache.ToArray();
|
saveTypePropertyCache = typePropertyCache.ToArray();
|
||||||
saveInheritsProperties = inheritsProperties.ToArray();
|
saveInheritsProperties = inheritsProperties.ToArray();
|
||||||
|
saveBreakInheritsProperties = breakInheritsProperties.ToArray();
|
||||||
FastReflectionExtensions.SetTypeCache();
|
FastReflectionExtensions.SetTypeCache();
|
||||||
savePropertyChangedMethods = propertyChangedMethods.ToArray();
|
savePropertyChangedMethods = propertyChangedMethods.ToArray();
|
||||||
}
|
}
|
||||||
@ -68,6 +71,15 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
saveInheritsProperties = null;
|
saveInheritsProperties = null;
|
||||||
}
|
}
|
||||||
|
if (saveBreakInheritsProperties != null)
|
||||||
|
{
|
||||||
|
breakInheritsProperties.Clear();
|
||||||
|
foreach (var item in saveBreakInheritsProperties)
|
||||||
|
{
|
||||||
|
breakInheritsProperties.TryAdd(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
saveBreakInheritsProperties = null;
|
||||||
|
}
|
||||||
if (savePropertyChangedMethods != null)
|
if (savePropertyChangedMethods != null)
|
||||||
{
|
{
|
||||||
propertyChangedMethods.Clear();
|
propertyChangedMethods.Clear();
|
||||||
@ -88,9 +100,13 @@ namespace CPF
|
|||||||
|
|
||||||
internal HybridDictionary<string, object> attachedValues;
|
internal HybridDictionary<string, object> attachedValues;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 继承属性的特性
|
/// 继承属性,不同继承类型分支下来的属性名可能相同但是属性ID不同,只能保存属性名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal HashSet<string> inheritsPropertyName;
|
internal HashSet<string> inheritsPropertyName;
|
||||||
|
/// <summary>
|
||||||
|
/// 终止继承属性,不同继承类型分支下来的属性名可能相同但是属性ID不同,只能保存属性名
|
||||||
|
/// </summary>
|
||||||
|
internal HashSet<string> breakInheritsPropertyName;
|
||||||
|
|
||||||
AttachedProperties attached;
|
AttachedProperties attached;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -178,7 +194,21 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
if (value.Command != null)
|
if (value.Command != null)
|
||||||
{
|
{
|
||||||
Commands.Add(propertyName, value.Command);
|
if (value.Command.Action != null)
|
||||||
|
{
|
||||||
|
Commands.Add(propertyName, value.Command.Action);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(value.Command.MethodName))
|
||||||
|
{
|
||||||
|
if (value.Command.Find != null)
|
||||||
|
{
|
||||||
|
Commands.Add(propertyName, value.Command.MethodName, value.Command.Find, value.Command.Parameters);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Commands.Add(propertyName, value.Command.MethodName, value.Command.Target, value.Command.Parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -217,8 +247,20 @@ namespace CPF
|
|||||||
var type = attached.GetType();
|
var type = attached.GetType();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var p = typeof(OptionalParameter<>).MakeGenericType(type.GetGenericArguments()[0]);
|
if (value is AttachedDescribe describe)
|
||||||
attached.Method.FastInvoke(attached.Target, this, Activator.CreateInstance(p, value));
|
{
|
||||||
|
var p = typeof(OptionalParameter<>).MakeGenericType(type.GetGenericArguments()[0]);
|
||||||
|
attached.Method.FastInvoke(attached.Target, this, Activator.CreateInstance(p, describe.Value));
|
||||||
|
var targetType = attached.Target.GetType();
|
||||||
|
var field = targetType.GetField("propertyName");
|
||||||
|
var name = field.FastGetValue(attached.Target).ToString();
|
||||||
|
AttachedNotify.Bindings.Add(name, describe.PropertyName, describe.Source, describe.BindingMode, describe.Convert, describe.ConvertBack, describe.SourceToTargetError, describe.TargetToSourceError);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var p = typeof(OptionalParameter<>).MakeGenericType(type.GetGenericArguments()[0]);
|
||||||
|
attached.Method.FastInvoke(attached.Target, this, Activator.CreateInstance(p, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -327,18 +369,31 @@ namespace CPF
|
|||||||
typePropertyCache.TryAdd(type, propertyList.ToArray());
|
typePropertyCache.TryAdd(type, propertyList.ToArray());
|
||||||
|
|
||||||
var l = new HashSet<string>();
|
var l = new HashSet<string>();
|
||||||
|
var b = new HashSet<string>();
|
||||||
foreach (var item in objInfo)
|
foreach (var item in objInfo)
|
||||||
{
|
{
|
||||||
if (item.Value is UIPropertyMetadataAttribute attribute && attribute.Inherits)
|
if (item.Value is UIPropertyMetadataAttribute attribute)
|
||||||
{
|
{
|
||||||
l.Add(attribute.PropertyName);
|
if (attribute.Inherits)
|
||||||
|
{
|
||||||
|
l.Add(attribute.PropertyName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b.Add(attribute.PropertyName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (l.Count == 0)
|
if (l.Count == 0)
|
||||||
{
|
{
|
||||||
l = null;
|
l = null;
|
||||||
}
|
}
|
||||||
|
if (b.Count == 0)
|
||||||
|
{
|
||||||
|
b = null;
|
||||||
|
}
|
||||||
inheritsProperties.TryAdd(type, l);
|
inheritsProperties.TryAdd(type, l);
|
||||||
|
breakInheritsProperties.TryAdd(type, b);
|
||||||
|
|
||||||
//Type tt = typeof(PropertyChangedAttribute);
|
//Type tt = typeof(PropertyChangedAttribute);
|
||||||
//var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, (a, b) => a.CustomAttributes.Any(c => c.AttributeType == tt), null);
|
//var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, (a, b) => a.CustomAttributes.Any(c => c.AttributeType == tt), null);
|
||||||
@ -444,6 +499,8 @@ namespace CPF
|
|||||||
//valueIndexs = new ByteArray((byte)objInfo.Count);
|
//valueIndexs = new ByteArray((byte)objInfo.Count);
|
||||||
valueIndexs = new byte[objInfo.Count];
|
valueIndexs = new byte[objInfo.Count];
|
||||||
inheritsPropertyName = inheritsProperties[type];
|
inheritsPropertyName = inheritsProperties[type];
|
||||||
|
breakInheritsPropertyName = breakInheritsProperties[type];
|
||||||
|
|
||||||
if (objInfo.Computed != null)
|
if (objInfo.Computed != null)
|
||||||
{
|
{
|
||||||
foreach (var item in objInfo.Computed)
|
foreach (var item in objInfo.Computed)
|
||||||
|
@ -213,7 +213,6 @@ namespace CPF.Design
|
|||||||
|
|
||||||
public void SetVisible(bool visible)
|
public void SetVisible(bool visible)
|
||||||
{
|
{
|
||||||
root.InputManager.TouchDevice.ClearPoints();
|
|
||||||
root.LayoutManager.ExecuteLayoutPass();
|
root.LayoutManager.ExecuteLayoutPass();
|
||||||
root.Invalidate();
|
root.Invalidate();
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
if (item.IsDisposed)
|
if (item.IsDisposed)
|
||||||
{
|
{
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
var rect = GetRect(item.Parent, item.GetContentBounds(), item);
|
var rect = GetRect(item.Parent, item.GetContentBounds(), item);
|
||||||
rect.Intersect(new Rect(new Point(), item.ActualSize));
|
rect.Intersect(new Rect(new Point(), item.ActualSize));
|
||||||
|
53
CPF/Obx.cs
Normal file
53
CPF/Obx.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF
|
||||||
|
{
|
||||||
|
public class Obx<T>: BindingDescribe where T : CpfObject, new()
|
||||||
|
{
|
||||||
|
public Obx(Expression<Func<T, object>> sourceProperty)
|
||||||
|
{
|
||||||
|
var expression = GetMemberExpression(sourceProperty.Body);
|
||||||
|
PropertyName = GetMemberPath(expression);
|
||||||
|
}
|
||||||
|
public Obx(Expression<Func<T, object>> sourceProperty, BindingMode binding)
|
||||||
|
{
|
||||||
|
var expression = GetMemberExpression(sourceProperty.Body);
|
||||||
|
PropertyName = GetMemberPath(expression);
|
||||||
|
BindingMode = binding;
|
||||||
|
}
|
||||||
|
public Obx(Expression<Func<T, object>> sourceProperty, BindingMode binding, Func<object, object> convert)
|
||||||
|
{
|
||||||
|
var expression = GetMemberExpression(sourceProperty.Body);
|
||||||
|
PropertyName = GetMemberPath(expression);
|
||||||
|
BindingMode = binding;
|
||||||
|
Convert = convert;
|
||||||
|
}
|
||||||
|
private static MemberExpression GetMemberExpression(Expression expression)
|
||||||
|
{
|
||||||
|
if (expression is MemberExpression memberExpression)
|
||||||
|
{
|
||||||
|
return memberExpression;
|
||||||
|
}
|
||||||
|
else if (expression is UnaryExpression unaryExpression)
|
||||||
|
{
|
||||||
|
return (MemberExpression)unaryExpression.Operand;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid expression. Expected a MemberExpression or UnaryExpression.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string GetMemberPath(MemberExpression expression)
|
||||||
|
{
|
||||||
|
if (expression.Expression is MemberExpression memberExpression)
|
||||||
|
{
|
||||||
|
return GetMemberPath(memberExpression) + "." + expression.Member.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression.Member.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1372,29 +1372,41 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 继承属性需要一级级传递,直到没有元素或者取消继承为止
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element"></param>
|
||||||
|
/// <param name="propertyName"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
void Inherits(UIElement element, string propertyName, object oldValue, object newValue)
|
void Inherits(UIElement element, string propertyName, object oldValue, object newValue)
|
||||||
{
|
{
|
||||||
if (!element.HasLocalOrStyleValue(propertyName, out var p))
|
if (!element.HasLocalOrStyleValue(propertyName, out var p))
|
||||||
{
|
{
|
||||||
element.inheritsSet = true;
|
|
||||||
//var p = element.GetPropertyMetadata(propertyName);
|
//var p = element.GetPropertyMetadata(propertyName);
|
||||||
if (p != null)
|
|
||||||
|
var ui = p as UIPropertyMetadataAttribute;
|
||||||
|
if (ui != null && ui.Inherits)
|
||||||
{
|
{
|
||||||
if (p is UIPropertyMetadataAttribute ui && ui.Inherits)
|
element.inheritsSet = true;
|
||||||
{
|
element.inheritsValues.Remove(propertyName);
|
||||||
element.inheritsValues.Remove(propertyName);
|
element.inheritsValues.Add(propertyName, new InheritsValue { Value = newValue, ValueForm = ValueFrom.Property });
|
||||||
element.inheritsValues.Add(propertyName, new InheritsValue { Value = newValue, ValueForm = ValueFrom.Property });
|
|
||||||
}
|
|
||||||
element.OnPropertyChanged(propertyName, oldValue, newValue, p);
|
element.OnPropertyChanged(propertyName, oldValue, newValue, p);
|
||||||
|
element.inheritsSet = false;
|
||||||
|
for (int i = 0; i < element.Children.Count; i++)
|
||||||
|
{
|
||||||
|
Inherits(element.children[i], propertyName, oldValue, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ui == null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < element.Children.Count; i++)
|
||||||
|
{
|
||||||
|
Inherits(element.children[i], propertyName, oldValue, newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
element.inheritsSet = false;
|
|
||||||
//if (propertyName != nameof(DataContext) || !element.HasLocalOrStyleValue(propertyName, out p))
|
//if (propertyName != nameof(DataContext) || !element.HasLocalOrStyleValue(propertyName, out p))
|
||||||
//{
|
//{
|
||||||
for (int i = 0; i < element.Children.Count; i++)
|
|
||||||
{
|
|
||||||
Inherits(element.children[i], propertyName, oldValue, newValue);
|
|
||||||
}
|
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2480,6 +2492,9 @@ namespace CPF
|
|||||||
viewRenderRect = true;
|
viewRenderRect = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要更新渲染区域
|
||||||
|
/// </summary>
|
||||||
[NotCpfProperty]
|
[NotCpfProperty]
|
||||||
internal bool viewRenderRect { get { return GetFlag(CoreFlags.viewRenderRect); } set { SetFlag(CoreFlags.viewRenderRect, value); } }
|
internal bool viewRenderRect { get { return GetFlag(CoreFlags.viewRenderRect); } set { SetFlag(CoreFlags.viewRenderRect, value); } }
|
||||||
//protected virtual void ArrangeCore(in Rect finalRect)
|
//protected virtual void ArrangeCore(in Rect finalRect)
|
||||||
@ -3441,7 +3456,7 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (p.HasLocalOrStyleValue(item, out _))
|
else if (p.HasLocalOrStyleValue(item, out var pa))
|
||||||
{
|
{
|
||||||
var value = p.GetValue(item);
|
var value = p.GetValue(item);
|
||||||
var old = GetValue(item);
|
var old = GetValue(item);
|
||||||
@ -3457,6 +3472,10 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p.breakInheritsPropertyName != null && p.breakInheritsPropertyName.Contains(item))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
p = p.Parent;
|
p = p.Parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
#if Net4||Net2
|
|
||||||
namespace System
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 值元组
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T1"></typeparam>
|
|
||||||
/// <typeparam name="T2"></typeparam>
|
|
||||||
[Serializable]
|
|
||||||
public struct ValueTuple<T1, T2>
|
|
||||||
{
|
|
||||||
public ValueTuple(T1 item1, T2 item2)
|
|
||||||
{
|
|
||||||
Item1 = item1;
|
|
||||||
Item2 = item2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T1 Item1;
|
|
||||||
|
|
||||||
public T2 Item2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net40;net5;net6</TargetFrameworks>
|
<TargetFrameworks>netcoreapp3.0;net40;net5;net6;net8</TargetFrameworks>
|
||||||
<ApplicationIcon />
|
<ApplicationIcon />
|
||||||
<StartupObject />
|
<StartupObject />
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
@ -110,6 +110,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DefineConstants Condition="'$(TargetFramework)'=='net40'">Net4</DefineConstants>
|
<DefineConstants Condition="'$(TargetFramework)'=='net40'">Net4</DefineConstants>
|
||||||
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
|
||||||
|
<Nullable>disable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp3.0|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp3.0|AnyCPU'">
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
|
@ -3,11 +3,81 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using CPF.Controls;
|
using CPF.Controls;
|
||||||
|
using static System.Net.Mime.MediaTypeNames;
|
||||||
|
|
||||||
namespace ConsoleApp1
|
namespace ConsoleApp1
|
||||||
{
|
{
|
||||||
|
public class data : CpfObject
|
||||||
|
{
|
||||||
|
public data test {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (data)GetValue();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public data()
|
||||||
|
{
|
||||||
|
test = this;
|
||||||
|
}
|
||||||
|
[PropertyMetadata(null)]
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (string)GetValue();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class dataa : CpfObject
|
||||||
|
{
|
||||||
|
public data test
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (data)GetValue();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public dataa()
|
||||||
|
{
|
||||||
|
// test = new data();
|
||||||
|
}
|
||||||
|
[PropertyMetadata(null)]
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (string)GetValue();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
class MainModel : CpfObject
|
class MainModel : CpfObject
|
||||||
{
|
{
|
||||||
|
public dataa Test1 {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (dataa)GetValue();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
[PropertyMetadata("默认值")]
|
[PropertyMetadata("默认值")]
|
||||||
public string Test
|
public string Test
|
||||||
{
|
{
|
||||||
@ -28,6 +98,7 @@ namespace ConsoleApp1
|
|||||||
|
|
||||||
public MainModel()
|
public MainModel()
|
||||||
{
|
{
|
||||||
|
Test1 = new dataa();
|
||||||
Items = new Collection<(string, string)>();
|
Items = new Collection<(string, string)>();
|
||||||
TestItems = new Collection<(string, int)>();
|
TestItems = new Collection<(string, int)>();
|
||||||
|
|
||||||
|
@ -188,6 +188,7 @@ namespace ConsoleApp1
|
|||||||
{
|
{
|
||||||
MarginTop = 0,
|
MarginTop = 0,
|
||||||
Content = "点击生成pdf",
|
Content = "点击生成pdf",
|
||||||
|
[nameof(Button.Content)]= new Obx<MainModel>(a => a.Test1.test.test.test.test.Name),
|
||||||
Commands =
|
Commands =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -235,7 +236,7 @@ namespace ConsoleApp1
|
|||||||
Content="另外一个演示窗体😍",
|
Content="另外一个演示窗体😍",
|
||||||
MarginTop=20,
|
MarginTop=20,
|
||||||
MarginLeft=20,
|
MarginLeft=20,
|
||||||
[nameof(Button.Click)]=(BindingDescribe)((s,e)=>
|
[nameof(Button.Click)]=new CommandDescribe((s,e)=>
|
||||||
{
|
{
|
||||||
var w = new Window1();
|
var w = new Window1();
|
||||||
w.DataContext = model;
|
w.DataContext = model;
|
||||||
@ -1386,7 +1387,8 @@ namespace ConsoleApp1
|
|||||||
MarginTop = 76,
|
MarginTop = 76,
|
||||||
Height = 23,
|
Height = 23,
|
||||||
Width = 219,
|
Width = 219,
|
||||||
[nameof(Slider.Value)]=new BindingDescribe(null, nameof(MainModel.ColumnWidth),BindingMode.OneWayToSource,null,a=>new GridLength((float)(double)a))
|
//[nameof(Slider.Value)]= new Obx<MainModel>(a => a.Type.Name),
|
||||||
|
[nameof(Slider.Value)]= new BindingDescribe(null, nameof(MainModel.ColumnWidth),BindingMode.OneWayToSource,null,a=>new GridLength((float)(double)a))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2419,10 +2421,10 @@ new TabItemTemplate{
|
|||||||
},
|
},
|
||||||
new TabItemTemplate
|
new TabItemTemplate
|
||||||
{
|
{
|
||||||
Header="布局",
|
Header="多级绑定",
|
||||||
Content=new Panel
|
Content=new Panel
|
||||||
{
|
{
|
||||||
Name = "布局",
|
Name = "多级绑定",
|
||||||
PresenterFor = this,
|
PresenterFor = this,
|
||||||
Width="100%",
|
Width="100%",
|
||||||
Height="100%",
|
Height="100%",
|
||||||
@ -2435,306 +2437,54 @@ new TabItemTemplate{
|
|||||||
Orientation= Orientation.Vertical,
|
Orientation= Orientation.Vertical,
|
||||||
Children=
|
Children=
|
||||||
{
|
{
|
||||||
new Button
|
|
||||||
|
new TextBlock
|
||||||
{
|
{
|
||||||
Content="StackPanel的Vertical"
|
[nameof(TextBlock.Text)]= new Obx<MainModel>(a => a.Test1.test.test.test.test.Name,
|
||||||
},
|
BindingMode.OneWay),
|
||||||
new Button
|
Name = "hmbb"
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new StackPanel
|
|
||||||
{
|
|
||||||
BorderStroke = "5,Solid",
|
|
||||||
BorderFill = "#B4B4B4",
|
|
||||||
MarginLeft=80,
|
|
||||||
MarginTop=50,
|
|
||||||
Orientation= Orientation.Horizontal,
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="StackPanel的Horizontal"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="Margin调间距",
|
|
||||||
MarginLeft=5
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new WrapPanel
|
|
||||||
{
|
|
||||||
MarginRight=10,
|
|
||||||
MarginTop=10,
|
|
||||||
Width="50%",
|
|
||||||
Orientation= Orientation.Horizontal,
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="WrapPanel的Horizontal"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="Margin调间距",
|
|
||||||
MarginLeft=5
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="宽度不够"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="可以自动换行"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Grid
|
|
||||||
{
|
|
||||||
RenderTransform=new RotateTransform(10),
|
|
||||||
Name="testGrid",
|
|
||||||
Background="#999",
|
|
||||||
Width="80%",
|
|
||||||
Height="60%",
|
|
||||||
MarginTop=120,
|
|
||||||
MarginLeft=20,
|
|
||||||
ColumnDefinitions=
|
|
||||||
{
|
|
||||||
new ColumnDefinition
|
|
||||||
{
|
|
||||||
Width="40*"
|
|
||||||
},
|
|
||||||
new ColumnDefinition
|
|
||||||
{
|
|
||||||
Width = "30*"
|
|
||||||
},
|
|
||||||
new ColumnDefinition
|
|
||||||
{
|
|
||||||
Width="200",
|
|
||||||
[nameof(ColumnDefinition.Width)]=nameof(MainModel.ColumnWidth)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
RowDefinitions=
|
|
||||||
{
|
|
||||||
new RowDefinition
|
|
||||||
{
|
|
||||||
Height="30*"
|
|
||||||
},
|
|
||||||
new RowDefinition
|
|
||||||
{
|
|
||||||
Height="30*"
|
|
||||||
},
|
|
||||||
new RowDefinition
|
|
||||||
{
|
|
||||||
Height="30*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new WrapPanel
|
|
||||||
{
|
|
||||||
Name="test",
|
|
||||||
Background="#a2f",
|
|
||||||
Width="100%",
|
|
||||||
Height="100%",
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="水平浮动布局231"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮2"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮3"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮4"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮5"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
new WrapPanel
|
|
||||||
{
|
|
||||||
Orientation= Orientation.Vertical,
|
|
||||||
Background="#27a",
|
|
||||||
Width="100%",
|
|
||||||
Height="100%",
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="垂直浮动布局"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮2"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮3"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮4"
|
|
||||||
},
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="按钮5"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
new TextBlock
|
|
||||||
{
|
|
||||||
Background="#ac2",
|
|
||||||
Width="100%",
|
|
||||||
Height="100%",
|
|
||||||
Text="Grid布局。。。"
|
|
||||||
},
|
|
||||||
2,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
new Panel
|
|
||||||
{
|
|
||||||
Background="#b1a",
|
|
||||||
MarginLeft=0,
|
|
||||||
MarginRight=0,
|
|
||||||
Children=
|
|
||||||
{
|
|
||||||
new Button
|
|
||||||
{
|
|
||||||
Content="跨列",
|
|
||||||
Width="50%"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
new TextBlock
|
|
||||||
{
|
|
||||||
Background="#186",
|
|
||||||
Height="100%",
|
|
||||||
Text="跨行"
|
|
||||||
},
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
},
|
},
|
||||||
new TextBox
|
new TextBox
|
||||||
{
|
{
|
||||||
MarginLeft=10,
|
Width = 130,
|
||||||
Size=SizeField.Fill,
|
Height= 60,
|
||||||
Text="元素变换,可以旋转,倾斜,缩放等操作",
|
Background =Color.Gray,
|
||||||
Attacheds=
|
[nameof(TextBox.Text)]= new Obx<MainModel>(a => a.Test1.test.test.test.test.Name,
|
||||||
{
|
BindingMode.OneWayToSource),
|
||||||
{
|
|
||||||
Grid.ColumnIndex,
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new Button
|
new Button
|
||||||
{
|
{
|
||||||
Content=new SVG("res://ConsoleApp1/test.svg")
|
Content="创建对象",
|
||||||
|
[nameof(Button.Click)]=new CommandDescribe((s,e)=>
|
||||||
{
|
{
|
||||||
MarginLeft = 0,
|
data a = new data();
|
||||||
MarginTop = 0,
|
a.test.test.test.Name = "666666";
|
||||||
Height = 85,
|
(DataContext as MainModel).Test1.test = a;
|
||||||
Width=170,
|
})
|
||||||
Stretch= Stretch.Uniform,
|
},
|
||||||
},
|
|
||||||
Width=104,
|
|
||||||
Height=55,
|
|
||||||
MarginLeft=60,
|
|
||||||
MarginTop=120,
|
|
||||||
Commands=
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Button.Click),
|
|
||||||
(s,e)=> Animation((Button)s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new DockPanel
|
|
||||||
{
|
|
||||||
LastChildFill = false,
|
|
||||||
Width=200,
|
|
||||||
Height=200,
|
|
||||||
MarginRight=0,
|
|
||||||
MarginTop=50,
|
|
||||||
Background="#f00",
|
|
||||||
Children =
|
|
||||||
{
|
|
||||||
new Button
|
new Button
|
||||||
{
|
{
|
||||||
Content="Right",
|
Content="删除对象",
|
||||||
Height="100%",
|
[nameof(Button.Click)]=new CommandDescribe((s,e)=>
|
||||||
Attacheds =
|
|
||||||
{
|
{
|
||||||
{
|
data a = new data();
|
||||||
DockPanel.Dock,
|
a.test.test.Name = "666666";
|
||||||
Dock.Right
|
(DataContext as MainModel).Test1.test.test = null;
|
||||||
}
|
})
|
||||||
}
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content="添加对象",
|
||||||
|
[nameof(Button.Click)]=new CommandDescribe((s,e)=>
|
||||||
|
{
|
||||||
|
data a = new data();
|
||||||
|
a.test.test.Name = "666666";
|
||||||
|
(DataContext as MainModel).Test1.test.test = a;
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Slider
|
|
||||||
{
|
|
||||||
Maximum = 300,
|
|
||||||
Value = 200,
|
|
||||||
MarginLeft = 252,
|
|
||||||
MarginTop = 76,
|
|
||||||
Height = 23,
|
|
||||||
Width = 219,
|
|
||||||
[nameof(Slider.Value)]=new BindingDescribe(null, nameof(MainModel.ColumnWidth),BindingMode.OneWayToSource,null,a=>new GridLength((float)(double)a))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
BIN
Other/yunchaobi.gif
Normal file
BIN
Other/yunchaobi.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 MiB |
25
README.md
25
README.md
@ -3,12 +3,12 @@
|
|||||||
#### 介绍
|
#### 介绍
|
||||||
C#跨平台UI框架
|
C#跨平台UI框架
|
||||||
|
|
||||||
提供NETStandard2.0和net4的库,通过Netcore可以跨平台,支持Windows、Mac、Linux,Net4的可以支持XP。各个平台运行效果一致,不依赖系统控件。
|
提供NETStandard2.0和net4的库,通过Netcore可以跨平台,支持Windows、Mac、Linux,Net4的可以支持XP。各个平台运行效果一致,不依赖系统控件。<br/>
|
||||||
支持窗体,控件任意透明,支持异形窗体,支持SVG图标显示。
|
支持窗体,控件任意透明,支持异形窗体,支持SVG图标显示。<br/>
|
||||||
支持动画,数据绑定,Mvvm模式,CSS等,简化依赖属性,数据绑定的写法,提供数据上下文和命令上下文来绑定,直接用CSS和C#代码描述。
|
支持动画,数据绑定,Mvvm模式,CSS等,简化依赖属性,数据绑定的写法,提供数据上下文和命令上下文来绑定,直接用CSS和C#代码描述。<br/>
|
||||||
提供设计器生成C#代码和开发者工具查看和调试元素
|
提供设计器生成C#代码和开发者工具查看和调试元素<br/>
|
||||||
和WPF一样的理念,任何控件都可以任意设计模板来实现各种效果
|
和WPF一样的理念,任何控件都可以任意设计模板来实现各种效果<br/>
|
||||||
除了使用平台相关API之外,基本可以实现一次编写,到处运行
|
除了使用平台相关API之外,基本可以实现一次编写,到处运行<br/>
|
||||||
全面支持国产化,支持国产Linux + 龙芯、飞腾、兆芯、海光等CPU平台
|
全面支持国产化,支持国产Linux + 龙芯、飞腾、兆芯、海光等CPU平台
|
||||||
|
|
||||||

|

|
||||||
@ -17,7 +17,9 @@ C#跨平台UI框架
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Apache License 2.0
|

|
||||||
|
|
||||||
|
**Apache License 2.0**
|
||||||
|
|
||||||
#### 软件架构
|
#### 软件架构
|
||||||
软件架构说明
|
软件架构说明
|
||||||
@ -29,6 +31,14 @@ CPF为主要框架,CPF.Skia为用skia做图形适配,CPF.Windows、CPF.Linux
|
|||||||
|
|
||||||
直接克隆/下载就可以编译,直接启动ConsoleApp1看运行效果
|
直接克隆/下载就可以编译,直接启动ConsoleApp1看运行效果
|
||||||
|
|
||||||
|
CPF使用文档 http://cpf.cskin.net/Course/#/
|
||||||
|
|
||||||
|
#### 扩展库
|
||||||
|
|
||||||
|
https://gitee.com/csharpui/cpf.cef 使用CPF对cef的封装,跨平台浏览器控件
|
||||||
|
|
||||||
|
https://gitee.com/csharpui/cpf.vlc 使用CPF对vlc的封装,跨平台视频播放控件
|
||||||
|
|
||||||
#### 关于设计器
|
#### 关于设计器
|
||||||
|
|
||||||
设计器不开源,设计器是需要另外收费的,免费模式可以刷新和预览,不能拖拽和审查元素,可以免费试用VIP一个月
|
设计器不开源,设计器是需要另外收费的,免费模式可以刷新和预览,不能拖拽和审查元素,可以免费试用VIP一个月
|
||||||
@ -51,3 +61,4 @@ CPF为主要框架,CPF.Skia为用skia做图形适配,CPF.Windows、CPF.Linux
|
|||||||
3. 提交代码
|
3. 提交代码
|
||||||
4. 新建 Pull Request
|
4. 新建 Pull Request
|
||||||
|
|
||||||
|
QQ群:894952004
|
||||||
|
Loading…
x
Reference in New Issue
Block a user