From 6d5acbdfacf6e9dfc7133332c13f6fbbfb6cd805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=9E=E8=89=B2=20=E5=BC=80?= <1694439208@qq.com> Date: Mon, 27 Nov 2023 15:57:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BA=86=E5=A4=9A=E7=BA=A7?= =?UTF-8?q?=E7=BB=91=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CPF/Binding.cs | 78 +++++--- CPF/BindingDescribe.cs | 2 + CPF/Bindings.cs | 3 + CPF/Obx.cs | 53 ++++++ ConsoleApp1/ConsoleApp1.csproj | 2 +- ConsoleApp1/MainModel.cs | 41 +++++ ConsoleApp1/Window2.cs | 314 +++------------------------------ 7 files changed, 173 insertions(+), 320 deletions(-) create mode 100644 CPF/Obx.cs diff --git a/CPF/Binding.cs b/CPF/Binding.cs index b6f20e6..9ebc15b 100644 --- a/CPF/Binding.cs +++ b/CPF/Binding.cs @@ -12,6 +12,7 @@ using System.Reflection.Emit; using System.Runtime.InteropServices; using System.Linq.Expressions; using System.Threading; +using System.Diagnostics; namespace CPF { @@ -366,29 +367,21 @@ namespace CPF } return; } - //CpfObject s = Source.Target as CpfObject; - //if (s == null) - //{ - // var p = Source.Target.GetType().GetProperty(SourcePropertyName); - // if (p == null) - // { - // throw new Exception("未找到" + Source.Target + "的属性:" + SourcePropertyName); - // } - // value = p.FastGetValue(Source.Target); - //} - //else - //{ - // if (s.HasProperty(SourcePropertyName)) - // { - // value = s.GetValue(SourcePropertyName); - // } - // else - // { - // var p = s.Type.GetProperty(SourcePropertyName); - // value = p.FastGetValue(Source.Target); - // } - //} - value = Source.Target.GetPropretyValue(SourcePropertyName); + /*var SourcePropertyNames = SourcePropertyName.Split('.'); + if (SourcePropertyNames.Length > 1) { + value = Source.Target; + for (int i = 0; i < SourcePropertyNames.Length; i++) + { + value = value.GetPropretyValue(SourcePropertyNames[i]); + } + } + else + { + value = Source.Target.GetPropretyValue(SourcePropertyName); + }*/ + value = GetPropertySource(SourcePropertyName, Source.Target); + value = value.GetPropretyValue(SourcePropertyName.Split('.').LastOrDefault()); + if (Convert != null) { value = Convert(value); @@ -453,8 +446,18 @@ namespace CPF { 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; + } + Target.SetValue(nv, SourcePropertyNames.LastOrDefault()); //b.Type.GetProperty(SourcePropertyName).FastSetValue(b, nv); - b.SetValue(SourcePropertyName, nv); } } else @@ -533,7 +536,8 @@ namespace CPF } 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; //object value; @@ -557,6 +561,27 @@ 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++) + { + Target = Target.GetPropretyValue(SourcePropertyNames[i]) as CpfObject; + } + return Target; + } + catch (Exception ex) + { + throw new Exception("错误:{ex}"); + } + } internal void RegisterPropertyChanged(INotifyPropertyChanged notify) { @@ -564,7 +589,8 @@ namespace CPF //{ // throw new Exception("错误"); //} - RegisterPropertyChanged(notify, PropertyChanged); + var notifySource = GetPropertySource(this.SourcePropertyName, notify); + RegisterPropertyChanged(notifySource as INotifyPropertyChanged, PropertyChanged); } internal void CancellationPropertyChanged(INotifyPropertyChanged notify) { diff --git a/CPF/BindingDescribe.cs b/CPF/BindingDescribe.cs index 1b807e3..8bae5ac 100644 --- a/CPF/BindingDescribe.cs +++ b/CPF/BindingDescribe.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using System.ComponentModel; +using System.Linq.Expressions; namespace CPF { @@ -16,6 +17,7 @@ namespace CPF { PropertyName = sourceProperty; } + public BindingDescribe(string sourceProperty, BindingMode binding) { PropertyName = sourceProperty; diff --git a/CPF/Bindings.cs b/CPF/Bindings.cs index 1f65a40..19d86a4 100644 --- a/CPF/Bindings.cs +++ b/CPF/Bindings.cs @@ -7,6 +7,7 @@ using System.Linq; using CPF.Controls; using System.Linq.Expressions; using System.Reflection; +using System.Diagnostics; namespace CPF { @@ -102,6 +103,7 @@ namespace CPF else { //((INotifyPropertyChanged)source).PropertyChanged += b.PropertyChanged; + b.RegisterPropertyChanged((INotifyPropertyChanged)source); b.SourceToTarget(); } @@ -114,6 +116,7 @@ namespace CPF { b.SourceToTarget(); } + //Debug.WriteLine($"sourcePropertyName:{sourcePropertyName},bindingMode:{bindingMode}"); return b; } /// diff --git a/CPF/Obx.cs b/CPF/Obx.cs new file mode 100644 index 0000000..668e0ab --- /dev/null +++ b/CPF/Obx.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace CPF +{ + public class Obx: BindingDescribe where T : CpfObject, new() + { + public Obx(Expression> sourceProperty) + { + var expression = GetMemberExpression(sourceProperty.Body); + PropertyName = GetMemberPath(expression); + } + public Obx(Expression> sourceProperty, BindingMode binding) + { + var expression = GetMemberExpression(sourceProperty.Body); + PropertyName = GetMemberPath(expression); + BindingMode = binding; + } + public Obx(Expression> sourceProperty, BindingMode binding, Func 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; + } + } +} diff --git a/ConsoleApp1/ConsoleApp1.csproj b/ConsoleApp1/ConsoleApp1.csproj index e85ff54..29ad6f2 100644 --- a/ConsoleApp1/ConsoleApp1.csproj +++ b/ConsoleApp1/ConsoleApp1.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0;net40;net5;net6 + netcoreapp3.0;net40;net5;net6;net8 WinExe diff --git a/ConsoleApp1/MainModel.cs b/ConsoleApp1/MainModel.cs index f3e5e6c..323879a 100644 --- a/ConsoleApp1/MainModel.cs +++ b/ConsoleApp1/MainModel.cs @@ -3,11 +3,51 @@ using System; using System.Collections.Generic; using System.Text; using CPF.Controls; +using static System.Net.Mime.MediaTypeNames; namespace ConsoleApp1 { + public class data : CpfObject + { + public data test { + get + { + return (data)GetValue(); + } + set + { + SetValue(value); + } + } + public data() + { + test = this; + } + [PropertyMetadata("我是默认的")] + public string Name + { + get + { + return (string)GetValue(); + } + set + { + SetValue(value); + } + } + } class MainModel : CpfObject { + public data Test1 { + get + { + return (data)GetValue(); + } + set + { + SetValue(value); + } + } [PropertyMetadata("默认值")] public string Test { @@ -28,6 +68,7 @@ namespace ConsoleApp1 public MainModel() { + Test1 = new data(); Items = new Collection<(string, string)>(); TestItems = new Collection<(string, int)>(); diff --git a/ConsoleApp1/Window2.cs b/ConsoleApp1/Window2.cs index a913a05..c29cc75 100644 --- a/ConsoleApp1/Window2.cs +++ b/ConsoleApp1/Window2.cs @@ -188,6 +188,7 @@ namespace ConsoleApp1 { MarginTop = 0, Content = "点击生成pdf", + [nameof(Button.Content)]= new Obx(a => a.Test1.test.test.test.test.Name), Commands = { { @@ -235,7 +236,7 @@ namespace ConsoleApp1 Content="另外一个演示窗体😍", MarginTop=20, MarginLeft=20, - [nameof(Button.Click)]=(BindingDescribe)((s,e)=> + [nameof(Button.Click)]=new CommandDescribe((s,e)=> { var w = new Window1(); w.DataContext = model; @@ -1386,7 +1387,8 @@ namespace ConsoleApp1 MarginTop = 76, Height = 23, 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(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 { - Header="布局", + Header="多级绑定", Content=new Panel { - Name = "布局", + Name = "多级绑定", PresenterFor = this, Width="100%", Height="100%", @@ -2435,306 +2437,32 @@ new TabItemTemplate{ Orientation= Orientation.Vertical, Children= { - new Button + + new TextBlock { - Content="StackPanel的Vertical" - }, - new Button - { - 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 + [nameof(TextBlock.Text)]= new Obx(a => a.Test1.test.test.test.test.Name, + BindingMode.OneWay), + Name = "hmbb" }, new TextBox { - MarginLeft=10, - Size=SizeField.Fill, - Text="元素变换,可以旋转,倾斜,缩放等操作", - Attacheds= - { - { - Grid.ColumnIndex, - 1 - } - } + Width = 130, + Height= 60, + Background =Color.Gray, + [nameof(TextBox.Text)]= new Obx(a => a.Test1.test.test.test.test.Name, + BindingMode.OneWayToSource), }, new Button { - Content=new SVG("res://ConsoleApp1/test.svg") + Content="按钮", + [nameof(Button.Click)]=new CommandDescribe((s,e)=> { - MarginLeft = 0, - MarginTop = 0, - Height = 85, - 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 - { - Content="Right", - Height="100%", - Attacheds = - { - { - DockPanel.Dock, - Dock.Right - } - } + (DataContext as MainModel).Test1.test.test.test.test.Name = "666666"; + }) }, } }, - 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)) - }, + } } },