From 4e23e93d9dff9f7401818f2fdcee644e3dbaf533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=BA=A2=E5=B8=BD?= <761716178@qq.com> Date: Thu, 30 Nov 2023 15:12:23 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8C=96=E8=A7=A6=E5=8F=91=E5=99=A8?= =?UTF-8?q?=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CPF.Skia/GlView.cs | 4 ++ CPF/BindingDescribe.cs | 53 +++++++++++++- CPF/Controls/ContentTemplate.cs | 53 +++++++++++++- CPF/Controls/ListBoxItem.cs | 7 +- CPF/CpfObject.cs | 23 +++++- CPF/Styling/Trigger.cs | 112 +++++++++++++++++++++++++++++- CPF/UIElement.cs | 17 +++++ ConsoleApp1/Program.cs | 2 +- ConsoleApp1/Window1.cs | 119 +++++++++++++++++++++++++++----- 9 files changed, 362 insertions(+), 28 deletions(-) diff --git a/CPF.Skia/GlView.cs b/CPF.Skia/GlView.cs index 4038d16..f2431c6 100644 --- a/CPF.Skia/GlView.cs +++ b/CPF.Skia/GlView.cs @@ -20,6 +20,10 @@ namespace CPF.Skia SKImage image; SKPaint paint; GRBackendTexture backendTexture; + /// + /// 支持OpenGL绘制的控件,在GLRender事件里绘制,开启GPU硬件加速才能使用 new SkiaDrawingFactory { UseGPU = true } + /// + public GLView() { } //IGlContext context; protected unsafe override void OnRender(DrawingContext dc) diff --git a/CPF/BindingDescribe.cs b/CPF/BindingDescribe.cs index 8bae5ac..ec0f1ce 100644 --- a/CPF/BindingDescribe.cs +++ b/CPF/BindingDescribe.cs @@ -17,29 +17,54 @@ namespace CPF { PropertyName = sourceProperty; } - + public BindingDescribe(string sourceProperty, BindingMode binding) { PropertyName = sourceProperty; BindingMode = binding; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// public BindingDescribe(object source, string sourceProperty, BindingMode binding) { PropertyName = sourceProperty; BindingMode = binding; Source = source; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// public BindingDescribe(object source, string sourceProperty) { PropertyName = sourceProperty; Source = source; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// public BindingDescribe(object source, string sourceProperty, Func convert) { PropertyName = sourceProperty; Source = source; Convert = convert; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// + /// public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func convert) { BindingMode = binding; @@ -47,6 +72,14 @@ namespace CPF Source = source; Convert = convert; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// + /// + /// public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func convert, Func convertBack) { BindingMode = binding; @@ -55,6 +88,16 @@ namespace CPF Convert = convert; ConvertBack = convertBack; } + /// + /// 设置绑定 + /// + /// 如果是int或者byte,0是自己,1是Parent,2是Parent.Parent.... + /// + /// + /// + /// + /// + /// public BindingDescribe(object source, string sourceProperty, BindingMode binding, Func convert, Func convertBack, Action SourceToTargetError, Action TargetToSourceError) { BindingMode = binding; @@ -81,6 +124,10 @@ namespace CPF /// 简化绑定命令的命令,如果设置了该属性,则使用命令绑定 /// public CommandDescribe Command { get; set; } + /// + /// 简化触发器设置 + /// + public CPF.Styling.TriggerDescribe Trigger { get; set; } //public CpfObject Owner { get; internal set; } @@ -355,6 +402,10 @@ namespace CPF { return new BindingDescribe { Command = command }; } + public static implicit operator BindingDescribe(CPF.Styling.TriggerDescribe trigger) + { + return new BindingDescribe { Trigger = trigger }; + } public static implicit operator BindingDescribe((string sourceProperty, BindingMode binding) item) { return new BindingDescribe { PropertyName = item.sourceProperty, BindingMode = item.binding }; diff --git a/CPF/Controls/ContentTemplate.cs b/CPF/Controls/ContentTemplate.cs index ab2ef36..3a982fc 100644 --- a/CPF/Controls/ContentTemplate.cs +++ b/CPF/Controls/ContentTemplate.cs @@ -10,7 +10,7 @@ namespace CPF.Controls /// 内容模板 /// [Description("内容模板"), Browsable(false)] - public class ContentTemplate : Decorator + public class ContentTemplate : Control { [PropertyMetadata(null)] public object Content @@ -85,9 +85,56 @@ namespace CPF.Controls overridePropertys.Override(nameof(Width), new UIPropertyMetadataAttribute(typeof(FloatField), "100%", UIPropertyOptions.AffectsMeasure)); overridePropertys.Override(nameof(Height), new UIPropertyMetadataAttribute(typeof(FloatField), "100%", UIPropertyOptions.AffectsMeasure)); } - //protected override Size MeasureOverride(in Size availableSize) + + /// + /// 获取或设置 单一子元素。 + /// + [Browsable(false)] + protected UIElement Child + { + get { return GetValue(); } + set { SetValue(value); } + } + + [PropertyChanged(nameof(Child))] + void OnChild(object newValue, object oldValue, PropertyMetadataAttribute attribute) + { + var o = oldValue as UIElement; + if (o != null) + { + Children.Remove(o); + } + var c = newValue as UIElement; + if (c != null) + { + Children.Add(c); + } + } + //protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata) //{ - // return base.MeasureOverride(availableSize); + // base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata); + // if (propertyName == nameof(Child)) + // { + // var o = oldValue as UIElement; + // if (o != null) + // { + // Children.Remove(o); + // } + // var c = newValue as UIElement; + // if (c != null) + // { + // Children.Add(c); + // } + // } //} + + protected override void OnUIElementRemoved(UIElementRemovedEventArgs e) + { + base.OnUIElementRemoved(e); + if (e.Element == Child) + { + Child = null; + } + } } } diff --git a/CPF/Controls/ListBoxItem.cs b/CPF/Controls/ListBoxItem.cs index 89fa0c7..b2c9fd7 100644 --- a/CPF/Controls/ListBoxItem.cs +++ b/CPF/Controls/ListBoxItem.cs @@ -90,8 +90,11 @@ namespace CPF.Controls Name = "contentPresenter", PresenterFor = this }); - Triggers.Add(new Styling.Trigger { Property = nameof(IsMouseOver), PropertyConditions = a => (bool)a && !IsSelected, Setters = { { nameof(Background), "229,243,251" } } }); - Triggers.Add(new Styling.Trigger { Property = nameof(IsSelected), Setters = { { nameof(Background), "203,233,246" } } }); + //Triggers.Add(new Styling.Trigger { Property = nameof(IsMouseOver), PropertyConditions = a => (bool)a && !IsSelected, Setters = { { nameof(Background), "229,243,251" } } }); + //Triggers.Add(new Styling.Trigger { Property = nameof(IsSelected), Setters = { { nameof(Background), "203,233,246" } } }); + + this[nameof(IsMouseOver)] = new Styling.TriggerDescribe(a => (bool)a && !IsSelected, (nameof(Background), "229,243,251")); + this[nameof(IsSelected)] = new Styling.TriggerDescribe((nameof(Background), "203,233,246")); } /// diff --git a/CPF/CpfObject.cs b/CPF/CpfObject.cs index b562a19..aaab87d 100644 --- a/CPF/CpfObject.cs +++ b/CPF/CpfObject.cs @@ -209,12 +209,33 @@ namespace CPF } } } + else if (value.Trigger != null) + { + OnAddTriggerDescribe(propertyName, value.Trigger); + } else { - Bindings.Add(propertyName, value.PropertyName, value.Source, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError); + if (value.Source is int layer) + { + Bindings.Add(propertyName, value.PropertyName, (byte)layer, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError); + } + if (value.Source is byte layer1) + { + Bindings.Add(propertyName, value.PropertyName, layer1, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError); + } + else + { + Bindings.Add(propertyName, value.PropertyName, value.Source, value.BindingMode, value.Convert, value.ConvertBack, value.SourceToTargetError, value.TargetToSourceError); + } } } } + + internal protected virtual void OnAddTriggerDescribe(string property, TriggerDescribe trigger) + { + + } + /// /// 读取或者设置附加属性,参数必须是附加属性 /// diff --git a/CPF/Styling/Trigger.cs b/CPF/Styling/Trigger.cs index de90d7f..0fdd4e3 100644 --- a/CPF/Styling/Trigger.cs +++ b/CPF/Styling/Trigger.cs @@ -43,8 +43,12 @@ namespace CPF.Styling this.PropertyConditions = DefaultPropertyConditions; } } - - bool DefaultPropertyConditions(object v) + /// + /// 属性为true的条件 + /// + /// + /// + public bool DefaultPropertyConditions(object v) { return (bool)v; } @@ -143,6 +147,110 @@ namespace CPF.Styling internal HybridDictionary> SetPropertys; } + public class TriggerDescribe + { + /// + /// 触发器 + /// + public TriggerDescribe(Relation TargetRelation, Func PropertyConditions, params (string, object)[] propertyAndValues) + { + this.TargetRelation = TargetRelation; + this.PropertyConditions = PropertyConditions; + this.Setters = propertyAndValues; + } + /// + /// 触发器 + /// + public TriggerDescribe(params (string, object)[] propertyAndValues) + { + this.Setters = propertyAndValues; + } + /// + /// 触发器 + /// + public TriggerDescribe(Func PropertyConditions, params (string, object)[] propertyAndValues) + { + this.PropertyConditions = PropertyConditions; + this.Setters = propertyAndValues; + } + /// + /// 触发器 + /// + /// + /// + /// + /// + /// + /// + /// + public TriggerDescribe(Relation TargetRelation = null, Func PropertyConditions = default, Storyboard Animation = null, TimeSpan? AnimationDuration = null, uint AnimationIterationCount = 1, EndBehavior AnimationEndBehavior = EndBehavior.Recovery, params (string, object)[] propertyAndValues) + { + this.TargetRelation = TargetRelation; + this.PropertyConditions = PropertyConditions; + this.PropertyConditions = PropertyConditions; + this.Setters = propertyAndValues; + this.Animation = Animation; + if (AnimationDuration.HasValue) + { + this.AnimationDuration = AnimationDuration.Value; + } + this.AnimationIterationCount = AnimationIterationCount; + this.AnimationEndBehavior = AnimationEndBehavior; + } + + + + /// + /// 满足条件之后播放的动画 + /// + public Storyboard Animation { get; set; } + + ///// + ///// 条件属性 + ///// + //public string Property { get; set; } + + /// + /// 属性条件,参数是属性值,返回条件结果 + /// + public Func PropertyConditions { get; set; } + + public (string, object)[] Setters { get; set; } + + /// + /// 相对位置元素,用来设置值或者动画 + /// + public Relation TargetRelation { get; set; } + + + /// + /// 动画持续时间 + /// + public TimeSpan AnimationDuration + { + get; + set; + } = TimeSpan.FromSeconds(0.5); + + /// + /// 动画播放次数,0为无限循环 + /// + public uint AnimationIterationCount + { + get; + set; + } = 1; + + /// + /// 动画结束之后的行为 + /// + public EndBehavior AnimationEndBehavior + { + get; + set; + } = EndBehavior.Recovery; + } + //public enum Conditions //{ // NotEqual, diff --git a/CPF/UIElement.cs b/CPF/UIElement.cs index 4057dac..95c67cd 100644 --- a/CPF/UIElement.cs +++ b/CPF/UIElement.cs @@ -3280,6 +3280,23 @@ namespace CPF } } + protected internal override void OnAddTriggerDescribe(string property, TriggerDescribe trigger) + { + var t = new Trigger { Animation = trigger.Animation, AnimationDuration = trigger.AnimationDuration, AnimationEndBehavior = trigger.AnimationEndBehavior, AnimationIterationCount = trigger.AnimationIterationCount, PropertyConditions = trigger.PropertyConditions, TargetRelation = trigger.TargetRelation, Property = property }; + if (trigger.Setters != null && trigger.Setters.Length > 0) + { + foreach (var item in trigger.Setters) + { + t.Setters.Add(item.Item1, item.Item2); + } + } + if (t.PropertyConditions == null) + { + t.PropertyConditions = t.DefaultPropertyConditions; + } + Triggers.Add(t); + } + //Styles styles; protected override void Dispose(bool disposing) diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index e710cab..cf295bb 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -45,7 +45,7 @@ namespace ConsoleApp1 #endif }) , (OperatingSystemType.OSX, new CPF.Mac.MacPlatform(), new SkiaDrawingFactory { UseGPU = false }) - , (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory { UseGPU = false }) + , (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory { UseGPU = true }) #endif ); diff --git a/ConsoleApp1/Window1.cs b/ConsoleApp1/Window1.cs index aebd668..20abfe9 100644 --- a/ConsoleApp1/Window1.cs +++ b/ConsoleApp1/Window1.cs @@ -105,7 +105,7 @@ namespace ConsoleApp1 }, new RowDefinition { - + } }, }); @@ -419,7 +419,7 @@ namespace ConsoleApp1 }, new Separator { - + }, new MenuItem { @@ -429,10 +429,13 @@ namespace ConsoleApp1 new MenuItem { Header = "21", - Commands = - { - {nameof(MenuItem.Click),MenuItemClick } - } + Commands = + { + { + nameof(MenuItem.Click), + MenuItemClick + } + } }, new MenuItem { @@ -444,7 +447,10 @@ namespace ConsoleApp1 Header = "221", Commands = { - {nameof(MenuItem.Click),MenuItemClick } + { + nameof(MenuItem.Click), + MenuItemClick + } } }, new MenuItem @@ -452,7 +458,10 @@ namespace ConsoleApp1 Header = "222", Commands = { - {nameof(MenuItem.Click),MenuItemClick } + { + nameof(MenuItem.Click), + MenuItemClick + } } } } @@ -468,10 +477,13 @@ namespace ConsoleApp1 new MenuItem { Header = "31", - Commands = - { - {nameof(MenuItem.Click),MenuItemClick } - } + Commands = + { + { + nameof(MenuItem.Click), + MenuItemClick + } + } }, new MenuItem { @@ -1362,7 +1374,8 @@ namespace ConsoleApp1 }, new ListBox { - //Background="#aaa", + MarginLeft = 57, + MarginTop = 63,//Background="#aaa", Name="listbox", IsVirtualizing=true,//VirtualizationMode= VirtualizationMode.Recycling, SelectionMode= SelectionMode.Extended, @@ -1372,7 +1385,18 @@ namespace ConsoleApp1 { Width="100%", FontSize=22, - Tag=this, + Tag=this, + Template=(e,c)=>{ + c.Add(new Border + { + Background="#f00", + Height = "100%", + Width = "100%", + BorderFill = null, + Name = "contentPresenter", + PresenterFor = this + }); + } }, Bindings= { @@ -1398,6 +1422,65 @@ namespace ConsoleApp1 } } },//new Button{ Content="排序" }, + new ListBox + { + MarginLeft = 463, + MarginTop = 44, + Height = 431, + Width = 283, + Background = "white", + BorderFill = new SolidColorFill + { + Color = Color.Silver + }, + BorderThickness = new Thickness(0, 1, 0, 0), + BorderType = BorderType.BorderThickness, + ItemsPanel = new StackPanel + { + Orientation = Orientation.Horizontal + }, + ItemTemplate = new ListBoxItem + { + Width = 100, + MarginRight = 1, + FontSize = 16f, + BorderFill = "Silver", + BorderThickness = new Thickness(1), + Margin = new ThicknessField(1), + CornerRadius = new CornerRadius(2), + IsAntiAlias = true, + UseLayoutRounding = true, + BorderType = BorderType.BorderThickness, + Template=(e,c)=>{ + Children.Add(new Border + { + Background="#f00", + Height = "100%", + Width = "100%", + BorderFill = null, + Name = "contentPresenter", + PresenterFor = this + }); + } + //ContentTemplate = new ContentTemplate + //{ + // Size = SizeField.Fill, + // Content = new StackPanel + // { + // Orientation = Orientation.Horizontal, + // Size = SizeField.Fill, + // Children = + // { + // new TextBlock + // { + // //[nameof(TextBlock.Text)] = new BindingDescribe("Title",BindingMode.OneWay) + // Text = "test" + // } + // } + // }, + //}, + }, + } } } }, @@ -1719,7 +1802,7 @@ namespace ConsoleApp1 nameof(DragEnter), (s,e)=> { - //(e as DragEventArgs).DragEffects= DragDropEffects.Link; + //(e as DragEventArgs).DragEffects= DragDropEffects.Link; } }, } @@ -1762,7 +1845,7 @@ namespace ConsoleApp1 Content="模糊,你撸多了", Effect=new BlurEffect { - + } }, new Button @@ -1789,7 +1872,7 @@ namespace ConsoleApp1 Content="灰色", Effect=new GrayScaleEffect { - + } }, new Picture @@ -1998,7 +2081,7 @@ namespace ConsoleApp1 { new RowDefinition { - + }, }, Children =