From 84463bef4b410d731b8bc7d4d6a27189af253a36 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Sat, 30 Nov 2019 00:56:41 +0800 Subject: [PATCH 1/4] init branch --- .../HandyControlDemo_Core30.csproj | 3 +++ .../HandyControlDemo_Net_40.csproj | 3 +++ .../HandyControlDemo_Net_GE45.csproj | 3 +++ .../HandyControlDemo_Shared/Data/DemoInfo.json | 3 ++- .../HandyControlDemo_Shared.projitems | 7 +++++++ .../Img/LeftMainContent/TransformRelative_16x.png | Bin 0 -> 169 bytes .../Controls/RelativePanelDemoCtl.xaml | 8 ++++++++ .../Controls/RelativePanelDemoCtl.xaml.cs | 10 ++++++++++ .../Controls/Panel/RelativePanel.cs | 9 +++++++++ .../HandyControl_Shared.projitems | 1 + 10 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/TransformRelative_16x.png create mode 100644 src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml create mode 100644 src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml.cs create mode 100644 src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs diff --git a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj index e9ef66a4..afdbaac0 100644 --- a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj +++ b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj @@ -448,6 +448,9 @@ Resources\Img\LeftMainContent\View_Portrait_16x.png + + Resources\Img\LeftMainContent\TransformRelative_16x.png + diff --git a/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj b/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj index e5a658ad..65e72972 100644 --- a/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj +++ b/src/Net_40/HandyControlDemo_Net_40/HandyControlDemo_Net_40.csproj @@ -430,6 +430,9 @@ TextTemplatingFileGenerator MessageToken.cs + + Resources\Img\LeftMainContent\TransformRelative_16x.png + Resources\Img\LeftMainContent\View_Portrait_16x.png diff --git a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj index 1fa83a40..8a6b97f4 100644 --- a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj +++ b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj @@ -496,6 +496,9 @@ TextTemplatingFileGenerator MessageToken.cs + + Resources\Img\LeftMainContent\TransformRelative_16x.png + Resources\Img\LeftMainContent\View_Portrait_16x.png diff --git a/src/Shared/HandyControlDemo_Shared/Data/DemoInfo.json b/src/Shared/HandyControlDemo_Shared/Data/DemoInfo.json index 6c5f4f76..92439c37 100644 --- a/src/Shared/HandyControlDemo_Shared/Data/DemoInfo.json +++ b/src/Shared/HandyControlDemo_Shared/Data/DemoInfo.json @@ -40,7 +40,7 @@ [ "Gravatar", "GravatarDemoCtl", "User_16x", "" ], [ "Badge", "BadgeDemoCtl", "DotLarge_16x", "" ], [ "GotoTop", "GotoTopDemoCtl", "GoToTop_16x", "" ], - [ "SplitButton", "SplitButtonDemoCtl", "SplitButton_16x", "1" ], + [ "SplitButton", "SplitButtonDemoCtl", "SplitButton_16x", "" ], [ "ButtonGroup", "ButtonGroupDemoCtl", "ButtonGroup_16x", "" ], [ "ProgressButton", "ProgressButtonDemoCtl", "ProgressButton_16x", "" ], [ "ChatBubble", "ChatBubbleDemoCtl", "Bubble_16xLG", "" ], @@ -68,6 +68,7 @@ [ "Divider", "DividerDemoCtl", "DottedSplitter_16x", "1" ], [ "CirclePanel", "CirclePanelDemoCtl", "ColorWheel_16x", "" ], [ "Grid", "GridDemoCtl", "GridPane_16x", "" ], + [ "RelativePanel", "RelativePanelDemoCtl", "TransformRelative_16x", "1" ], [ "WaterfallPanel", "WaterfallPanelDemoCtl", "Panel_16x", "" ], [ "HoneycombPanel", "HoneycombPanelDemoCtl", "PolygonHexagon_16x", "" ], [ "TransitioningContentControl", "TransitioningContentControlDemoCtl", "TransitioningContentControl_16x", "" ], diff --git a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems index 6d09742c..4fe569a5 100644 --- a/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems +++ b/src/Shared/HandyControlDemo_Shared/HandyControlDemo_Shared.projitems @@ -182,6 +182,9 @@ RateDemoCtl.xaml + + RelativePanelDemoCtl.xaml + RunningBlockDemoCtl.xaml @@ -640,6 +643,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/TransformRelative_16x.png b/src/Shared/HandyControlDemo_Shared/Resources/Img/LeftMainContent/TransformRelative_16x.png new file mode 100644 index 0000000000000000000000000000000000000000..bf04a7a9a92bf580162b967a05aafe97208dde84 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMpkTD8 zi(^Pd+|kL7Tn7v|SZZhg|L=XN`}!0a7QyY=nyQClMA8x+6O+?kcTRH%_5RkYwlkqm zJBaJfnFc2Nv`7EuC|njh@JU87w?6CtRE6oKeg_(urm$q%pML+oin(`kw!O>ou5UnV O7(8A5T-G@yGywpb_&a9+ literal 0 HcmV?d00001 diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml new file mode 100644 index 00000000..b59bb5c8 --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml.cs b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml.cs new file mode 100644 index 00000000..747c9b57 --- /dev/null +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml.cs @@ -0,0 +1,10 @@ +namespace HandyControlDemo.UserControl +{ + public partial class RelativePanelDemoCtl + { + public RelativePanelDemoCtl() + { + InitializeComponent(); + } + } +} diff --git a/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs new file mode 100644 index 00000000..0c48f95a --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs @@ -0,0 +1,9 @@ +using System.Windows.Controls; + +namespace HandyControl.Controls +{ + public class RelativePanel : Panel + { + + } +} diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index bb56f6d3..233e5817 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -35,6 +35,7 @@ + From 23b9c41301f54b2cdc614525387e50a6d874a776 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Sat, 30 Nov 2019 01:16:57 +0800 Subject: [PATCH 2/4] add basic codes --- .../Controls/Panel/RelativePanel.cs | 168 +++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) diff --git a/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs index 0c48f95a..918c18c4 100644 --- a/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs +++ b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs @@ -1,9 +1,175 @@ -using System.Windows.Controls; +using System.Windows; +using System.Windows.Controls; +using HandyControl.Data; namespace HandyControl.Controls { public class RelativePanel : Panel { + #region Panel alignment relationships + public static readonly DependencyProperty AlignLeftWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignLeftWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignLeftWithPanelProperty, value); + + public static bool GetAlignLeftWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignLeftWithPanelProperty); + + public static readonly DependencyProperty AlignTopWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignTopWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignTopWithPanelProperty, value); + + public static bool GetAlignTopWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignTopWithPanelProperty); + + public static readonly DependencyProperty AlignRightWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignRightWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignRightWithPanelProperty, value); + + public static bool GetAlignRightWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignRightWithPanelProperty); + + public static readonly DependencyProperty AlignBottomWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignBottomWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignBottomWithPanelProperty, value); + + public static bool GetAlignBottomWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignBottomWithPanelProperty); + + public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignHorizontalCenterWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignHorizontalCenterWithPanelProperty, value); + + public static bool GetAlignHorizontalCenterWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignHorizontalCenterWithPanelProperty); + + public static readonly DependencyProperty AlignVerticalCenterWithPanelProperty = DependencyProperty.RegisterAttached( + "AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + + public static void SetAlignVerticalCenterWithPanel(DependencyObject element, bool value) + => element.SetValue(AlignVerticalCenterWithPanelProperty, value); + + public static bool GetAlignVerticalCenterWithPanel(DependencyObject element) + => (bool) element.GetValue(AlignVerticalCenterWithPanelProperty); + + #endregion + + #region Sibling alignment relationships + + public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached( + "AlignLeftWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignLeftWith(DependencyObject element, string value) + => element.SetValue(AlignLeftWithProperty, value); + + public static string GetAlignLeftWith(DependencyObject element) + => (string) element.GetValue(AlignLeftWithProperty); + + public static readonly DependencyProperty AlignTopWithProperty = DependencyProperty.RegisterAttached( + "AlignTopWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignTopWith(DependencyObject element, string value) + => element.SetValue(AlignTopWithProperty, value); + + public static string GetAlignTopWith(DependencyObject element) + => (string) element.GetValue(AlignTopWithProperty); + + public static readonly DependencyProperty AlignRightWithProperty = DependencyProperty.RegisterAttached( + "AlignRightWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignRightWith(DependencyObject element, string value) + => element.SetValue(AlignRightWithProperty, value); + + public static string GetAlignRightWith(DependencyObject element) + => (string) element.GetValue(AlignRightWithProperty); + + public static readonly DependencyProperty AlignBottomWithProperty = DependencyProperty.RegisterAttached( + "AlignBottomWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignBottomWith(DependencyObject element, string value) + => element.SetValue(AlignBottomWithProperty, value); + + public static string GetAlignBottomWith(DependencyObject element) + => (string) element.GetValue(AlignBottomWithProperty); + + public static readonly DependencyProperty AlignHorizontalCenterWithProperty = DependencyProperty.RegisterAttached( + "AlignHorizontalCenterWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignHorizontalCenterWith(DependencyObject element, string value) + => element.SetValue(AlignHorizontalCenterWithProperty, value); + + public static string GetAlignHorizontalCenterWith(DependencyObject element) + => (string) element.GetValue(AlignHorizontalCenterWithProperty); + + public static readonly DependencyProperty AlignVerticalCenterWithProperty = DependencyProperty.RegisterAttached( + "AlignVerticalCenterWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAlignVerticalCenterWith(DependencyObject element, string value) + => element.SetValue(AlignVerticalCenterWithProperty, value); + + public static string GetAlignVerticalCenterWith(DependencyObject element) + => (string) element.GetValue(AlignVerticalCenterWithProperty); + + #endregion + + #region Sibling positional relationships + + public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached( + "LeftOf", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetLeftOf(DependencyObject element, string value) + => element.SetValue(LeftOfProperty, value); + + public static string GetLeftOf(DependencyObject element) + => (string)element.GetValue(LeftOfProperty); + + public static readonly DependencyProperty AboveProperty = DependencyProperty.RegisterAttached( + "Above", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetAbove(DependencyObject element, string value) + => element.SetValue(AboveProperty, value); + + public static string GetAbove(DependencyObject element) + => (string)element.GetValue(AboveProperty); + + public static readonly DependencyProperty RightOfProperty = DependencyProperty.RegisterAttached( + "RightOf", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetRightOf(DependencyObject element, string value) + => element.SetValue(RightOfProperty, value); + + public static string GetRightOf(DependencyObject element) + => (string)element.GetValue(RightOfProperty); + + public static readonly DependencyProperty BelowProperty = DependencyProperty.RegisterAttached( + "Below", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + + public static void SetBelow(DependencyObject element, string value) + => element.SetValue(BelowProperty, value); + + public static string GetBelow(DependencyObject element) + => (string) element.GetValue(BelowProperty); + + #endregion + + protected override Size MeasureOverride(Size availableSize) + { + return availableSize; + } + + protected override Size ArrangeOverride(Size arrangeSize) + { + return arrangeSize; + } } } From fc1fa6fcf7917c74b79123b39e8b93598b19a281 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Tue, 10 Dec 2019 00:41:49 +0800 Subject: [PATCH 3/4] add RelativePanel --- .../Controls/RelativePanelDemoCtl.xaml | 57 +- .../Controls/{ => Panel}/Grid/Col.cs | 0 .../Controls/{ => Panel}/Grid/Row.cs | 0 .../Controls/Panel/RelativePanel.cs | 524 ++++++++++++++---- .../HandyControl_Shared.projitems | 4 +- .../Tools/Converter/ColLayoutConverter.cs | 3 +- 6 files changed, 482 insertions(+), 106 deletions(-) rename src/Shared/HandyControl_Shared/Controls/{ => Panel}/Grid/Col.cs (100%) rename src/Shared/HandyControl_Shared/Controls/{ => Panel}/Grid/Row.cs (100%) diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml index b59bb5c8..d68d7060 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml @@ -1,8 +1,59 @@  - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Shared/HandyControl_Shared/Controls/Grid/Col.cs b/src/Shared/HandyControl_Shared/Controls/Panel/Grid/Col.cs similarity index 100% rename from src/Shared/HandyControl_Shared/Controls/Grid/Col.cs rename to src/Shared/HandyControl_Shared/Controls/Panel/Grid/Col.cs diff --git a/src/Shared/HandyControl_Shared/Controls/Grid/Row.cs b/src/Shared/HandyControl_Shared/Controls/Panel/Grid/Row.cs similarity index 100% rename from src/Shared/HandyControl_Shared/Controls/Grid/Row.cs rename to src/Shared/HandyControl_Shared/Controls/Panel/Grid/Row.cs diff --git a/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs index 918c18c4..f2705d0e 100644 --- a/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs +++ b/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs @@ -1,4 +1,9 @@ -using System.Windows; +//reference doc : https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.RelativePanel + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; using System.Windows.Controls; using HandyControl.Data; @@ -6,10 +11,14 @@ namespace HandyControl.Controls { public class RelativePanel : Panel { - #region Panel alignment relationships + private readonly Graph _childGraph; + + public RelativePanel() => _childGraph = new Graph(); + + #region 容器对齐方式 public static readonly DependencyProperty AlignLeftWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignLeftWithPanel(DependencyObject element, bool value) => element.SetValue(AlignLeftWithPanelProperty, value); @@ -18,7 +27,7 @@ namespace HandyControl.Controls => (bool) element.GetValue(AlignLeftWithPanelProperty); public static readonly DependencyProperty AlignTopWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignTopWithPanel(DependencyObject element, bool value) => element.SetValue(AlignTopWithPanelProperty, value); @@ -27,7 +36,7 @@ namespace HandyControl.Controls => (bool) element.GetValue(AlignTopWithPanelProperty); public static readonly DependencyProperty AlignRightWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignRightWithPanel(DependencyObject element, bool value) => element.SetValue(AlignRightWithPanelProperty, value); @@ -36,7 +45,7 @@ namespace HandyControl.Controls => (bool) element.GetValue(AlignRightWithPanelProperty); public static readonly DependencyProperty AlignBottomWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignBottomWithPanel(DependencyObject element, bool value) => element.SetValue(AlignBottomWithPanelProperty, value); @@ -44,132 +53,449 @@ namespace HandyControl.Controls public static bool GetAlignBottomWithPanel(DependencyObject element) => (bool) element.GetValue(AlignBottomWithPanelProperty); + #endregion + + #region 元素间对齐方式 + + public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached( + "AlignLeftWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetAlignLeftWith(DependencyObject element, UIElement value) + => element.SetValue(AlignLeftWithProperty, value); + + public static UIElement GetAlignLeftWith(DependencyObject element) + => (UIElement) element.GetValue(AlignLeftWithProperty); + + public static readonly DependencyProperty AlignTopWithProperty = DependencyProperty.RegisterAttached( + "AlignTopWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetAlignTopWith(DependencyObject element, UIElement value) + => element.SetValue(AlignTopWithProperty, value); + + public static UIElement GetAlignTopWith(DependencyObject element) + => (UIElement) element.GetValue(AlignTopWithProperty); + + public static readonly DependencyProperty AlignRightWithProperty = DependencyProperty.RegisterAttached( + "AlignRightWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetAlignRightWith(DependencyObject element, UIElement value) + => element.SetValue(AlignRightWithProperty, value); + + public static UIElement GetAlignRightWith(DependencyObject element) + => (UIElement) element.GetValue(AlignRightWithProperty); + + public static readonly DependencyProperty AlignBottomWithProperty = DependencyProperty.RegisterAttached( + "AlignBottomWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetAlignBottomWith(DependencyObject element, UIElement value) + => element.SetValue(AlignBottomWithProperty, value); + + public static UIElement GetAlignBottomWith(DependencyObject element) + => (UIElement) element.GetValue(AlignBottomWithProperty); + + #endregion + + #region 元素间位置关系 + + public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached( + "LeftOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetLeftOf(DependencyObject element, UIElement value) + => element.SetValue(LeftOfProperty, value); + + public static UIElement GetLeftOf(DependencyObject element) + => (UIElement)element.GetValue(LeftOfProperty); + + public static readonly DependencyProperty AboveProperty = DependencyProperty.RegisterAttached( + "Above", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetAbove(DependencyObject element, UIElement value) + => element.SetValue(AboveProperty, value); + + public static UIElement GetAbove(DependencyObject element) + => (UIElement)element.GetValue(AboveProperty); + + public static readonly DependencyProperty RightOfProperty = DependencyProperty.RegisterAttached( + "RightOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetRightOf(DependencyObject element, UIElement value) + => element.SetValue(RightOfProperty, value); + + public static UIElement GetRightOf(DependencyObject element) + => (UIElement)element.GetValue(RightOfProperty); + + public static readonly DependencyProperty BelowProperty = DependencyProperty.RegisterAttached( + "Below", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); + + public static void SetBelow(DependencyObject element, UIElement value) + => element.SetValue(BelowProperty, value); + + public static UIElement GetBelow(DependencyObject element) + => (UIElement) element.GetValue(BelowProperty); + + #endregion + + #region 居中对齐方式 + public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignHorizontalCenterWithPanel(DependencyObject element, bool value) => element.SetValue(AlignHorizontalCenterWithPanelProperty, value); public static bool GetAlignHorizontalCenterWithPanel(DependencyObject element) - => (bool) element.GetValue(AlignHorizontalCenterWithPanelProperty); + => (bool)element.GetValue(AlignHorizontalCenterWithPanelProperty); public static readonly DependencyProperty AlignVerticalCenterWithPanelProperty = DependencyProperty.RegisterAttached( - "AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new PropertyMetadata(ValueBoxes.FalseBox)); + "AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); public static void SetAlignVerticalCenterWithPanel(DependencyObject element, bool value) => element.SetValue(AlignVerticalCenterWithPanelProperty, value); public static bool GetAlignVerticalCenterWithPanel(DependencyObject element) - => (bool) element.GetValue(AlignVerticalCenterWithPanelProperty); - - #endregion - - #region Sibling alignment relationships - - public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached( - "AlignLeftWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetAlignLeftWith(DependencyObject element, string value) - => element.SetValue(AlignLeftWithProperty, value); - - public static string GetAlignLeftWith(DependencyObject element) - => (string) element.GetValue(AlignLeftWithProperty); - - public static readonly DependencyProperty AlignTopWithProperty = DependencyProperty.RegisterAttached( - "AlignTopWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetAlignTopWith(DependencyObject element, string value) - => element.SetValue(AlignTopWithProperty, value); - - public static string GetAlignTopWith(DependencyObject element) - => (string) element.GetValue(AlignTopWithProperty); - - public static readonly DependencyProperty AlignRightWithProperty = DependencyProperty.RegisterAttached( - "AlignRightWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetAlignRightWith(DependencyObject element, string value) - => element.SetValue(AlignRightWithProperty, value); - - public static string GetAlignRightWith(DependencyObject element) - => (string) element.GetValue(AlignRightWithProperty); - - public static readonly DependencyProperty AlignBottomWithProperty = DependencyProperty.RegisterAttached( - "AlignBottomWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetAlignBottomWith(DependencyObject element, string value) - => element.SetValue(AlignBottomWithProperty, value); - - public static string GetAlignBottomWith(DependencyObject element) - => (string) element.GetValue(AlignBottomWithProperty); + => (bool)element.GetValue(AlignVerticalCenterWithPanelProperty); public static readonly DependencyProperty AlignHorizontalCenterWithProperty = DependencyProperty.RegisterAttached( - "AlignHorizontalCenterWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + "AlignHorizontalCenterWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); - public static void SetAlignHorizontalCenterWith(DependencyObject element, string value) + public static void SetAlignHorizontalCenterWith(DependencyObject element, UIElement value) => element.SetValue(AlignHorizontalCenterWithProperty, value); - public static string GetAlignHorizontalCenterWith(DependencyObject element) - => (string) element.GetValue(AlignHorizontalCenterWithProperty); + public static UIElement GetAlignHorizontalCenterWith(DependencyObject element) + => (UIElement)element.GetValue(AlignHorizontalCenterWithProperty); public static readonly DependencyProperty AlignVerticalCenterWithProperty = DependencyProperty.RegisterAttached( - "AlignVerticalCenterWith", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); + "AlignVerticalCenterWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender)); - public static void SetAlignVerticalCenterWith(DependencyObject element, string value) + public static void SetAlignVerticalCenterWith(DependencyObject element, UIElement value) => element.SetValue(AlignVerticalCenterWithProperty, value); - public static string GetAlignVerticalCenterWith(DependencyObject element) - => (string) element.GetValue(AlignVerticalCenterWithProperty); - - #endregion - - #region Sibling positional relationships - - public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached( - "LeftOf", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetLeftOf(DependencyObject element, string value) - => element.SetValue(LeftOfProperty, value); - - public static string GetLeftOf(DependencyObject element) - => (string)element.GetValue(LeftOfProperty); - - public static readonly DependencyProperty AboveProperty = DependencyProperty.RegisterAttached( - "Above", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetAbove(DependencyObject element, string value) - => element.SetValue(AboveProperty, value); - - public static string GetAbove(DependencyObject element) - => (string)element.GetValue(AboveProperty); - - public static readonly DependencyProperty RightOfProperty = DependencyProperty.RegisterAttached( - "RightOf", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetRightOf(DependencyObject element, string value) - => element.SetValue(RightOfProperty, value); - - public static string GetRightOf(DependencyObject element) - => (string)element.GetValue(RightOfProperty); - - public static readonly DependencyProperty BelowProperty = DependencyProperty.RegisterAttached( - "Below", typeof(string), typeof(RelativePanel), new PropertyMetadata(default(string))); - - public static void SetBelow(DependencyObject element, string value) - => element.SetValue(BelowProperty, value); - - public static string GetBelow(DependencyObject element) - => (string) element.GetValue(BelowProperty); + public static UIElement GetAlignVerticalCenterWith(DependencyObject element) + => (UIElement)element.GetValue(AlignVerticalCenterWithProperty); #endregion protected override Size MeasureOverride(Size availableSize) { - return availableSize; + foreach (UIElement child in InternalChildren) + { + child?.Measure(availableSize); + } + + return base.MeasureOverride(availableSize); } protected override Size ArrangeOverride(Size arrangeSize) { + _childGraph.Reset(arrangeSize); + + foreach (UIElement child in InternalChildren) + { + if (child == null) continue; + + var node = _childGraph.AddNode(child); + + node.AlignLeftWithNode = _childGraph.AddLink(node, GetAlignLeftWith(child)); + node.AlignTopWithNode = _childGraph.AddLink(node, GetAlignTopWith(child)); + node.AlignRightWithNode = _childGraph.AddLink(node, GetAlignRightWith(child)); + node.AlignBottomWithNode = _childGraph.AddLink(node, GetAlignBottomWith(child)); + + node.LeftOfNode = _childGraph.AddLink(node, GetLeftOf(child)); + node.AboveNode = _childGraph.AddLink(node, GetAbove(child)); + node.RightOfNode = _childGraph.AddLink(node, GetRightOf(child)); + node.BelowNode = _childGraph.AddLink(node, GetBelow(child)); + + node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetAlignHorizontalCenterWith(child)); + node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetAlignVerticalCenterWith(child)); + } + + if (_childGraph.CheckCyclic()) + { + throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete."); + } + return arrangeSize; } + + private class GraphNode + { + public Point Position { get; set; } + + public bool Arranged { get; set; } + + public UIElement Element { get; } + + public HashSet OutgoingNodes { get; } + + public GraphNode AlignLeftWithNode { get; set; } + + public GraphNode AlignTopWithNode { get; set; } + + public GraphNode AlignRightWithNode { get; set; } + + public GraphNode AlignBottomWithNode { get; set; } + + public GraphNode LeftOfNode { get; set; } + + public GraphNode AboveNode { get; set; } + + public GraphNode RightOfNode { get; set; } + + public GraphNode BelowNode { get; set; } + + public GraphNode AlignHorizontalCenterWith { get; set; } + + public GraphNode AlignVerticalCenterWith { get; set; } + + public GraphNode(UIElement element) + { + OutgoingNodes = new HashSet(); + Element = element; + } + } + + private class Graph + { + private readonly Dictionary _nodeDic; + + private Size _arrangeSize; + + public Graph() + { + _nodeDic = new Dictionary(); + } + + public GraphNode AddLink(GraphNode from, UIElement to) + { + if (to == null) return null; + + GraphNode nodeTo; + if (_nodeDic.ContainsKey(to)) + { + nodeTo = _nodeDic[to]; + } + else + { + nodeTo = new GraphNode(to); + _nodeDic[to] = nodeTo; + } + + from.OutgoingNodes.Add(nodeTo); + return nodeTo; + } + + public GraphNode AddNode(UIElement value) + { + if (!_nodeDic.ContainsKey(value)) + { + var node = new GraphNode(value); + _nodeDic.Add(value, node); + return node; + } + + return _nodeDic[value]; + } + + public void Reset(Size arrangeSize) + { + _arrangeSize = arrangeSize; + _nodeDic.Clear(); + } + + public bool CheckCyclic() => CheckCyclic(_nodeDic.Values, null); + + private bool CheckCyclic(IEnumerable nodes, HashSet set) + { + if (set == null) + { + set = new HashSet(); + } + + foreach (var node in nodes) + { + /* + * 该节点无任何依赖,所以从这里开始计算元素位置。 + * 因为无任何依赖,所以忽略同级元素 + */ + if (!node.Arranged && node.OutgoingNodes.Count == 0) + { + ArrangeChild(node, true); + continue; + } + + // 判断依赖元素是否全部排列完毕 + if (node.OutgoingNodes.All(item => item.Arranged)) + { + ArrangeChild(node); + continue; + } + + // 判断是否有循环 + if (!set.Add(node.Element)) return true; + + // 没有循环,且有依赖,则继续往下 + return CheckCyclic(node.OutgoingNodes, set); + } + + return false; + } + + private void ArrangeChild(GraphNode node, bool ignoneSibling = false) + { + var child = node.Element; + var childSize = child.DesiredSize; + var childPos = new Point(); + + #region 容器居中对齐 + + if (GetAlignHorizontalCenterWithPanel(child)) + { + childPos.X = (_arrangeSize.Width - childSize.Width) / 2; + } + + if (GetAlignVerticalCenterWithPanel(child)) + { + childPos.Y = (_arrangeSize.Height - childSize.Height) / 2; + } + + #endregion + + var alignLeftWithPanel = GetAlignLeftWithPanel(child); + var alignTopWithPanel = GetAlignTopWithPanel(child); + var alignRightWithPanel = GetAlignRightWithPanel(child); + var alignBottomWithPanel = GetAlignBottomWithPanel(child); + + if (!ignoneSibling) + { + #region 元素间位置 + + if (node.LeftOfNode != null) + { + childPos.X = node.LeftOfNode.Position.X - childSize.Width; + } + + if (node.AboveNode != null) + { + childPos.Y = node.AboveNode.Position.Y - childSize.Height; + } + + if (node.RightOfNode != null) + { + childPos.X = node.RightOfNode.Position.X + node.RightOfNode.Element.DesiredSize.Width; + } + + if (node.BelowNode != null) + { + childPos.Y = node.BelowNode.Position.Y + node.BelowNode.Element.DesiredSize.Height; + } + + #endregion + + #region 元素居中对齐 + + if (node.AlignHorizontalCenterWith != null) + { + childPos.X = node.AlignHorizontalCenterWith.Position.X + + (node.AlignHorizontalCenterWith.Element.DesiredSize.Width - childSize.Width) / 2; + } + + if (node.AlignVerticalCenterWith != null) + { + childPos.Y = node.AlignVerticalCenterWith.Position.Y + + (node.AlignVerticalCenterWith.Element.DesiredSize.Height - childSize.Height) / 2; + } + + #endregion + + #region 元素间对齐 + + if (node.AlignLeftWithNode != null) + { + childPos.X = node.AlignLeftWithNode.Position.X; + } + + if (node.AlignTopWithNode != null) + { + childPos.Y = node.AlignTopWithNode.Position.Y; + } + + if (node.AlignRightWithNode != null) + { + childPos.X = node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width; + } + + if (node.AlignBottomWithNode != null) + { + childPos.Y = node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height; + } + + #endregion + } + + #region 容器对齐 + + if (alignLeftWithPanel) + { + if (node.AlignRightWithNode != null) + { + childPos.X = (node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width) / 2; + } + else + { + childPos.X = 0; + } + } + + if (alignTopWithPanel) + { + if (node.AlignBottomWithNode != null) + { + childPos.Y = (node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height) / 2; + } + else + { + childPos.Y = 0; + } + } + + if (alignRightWithPanel) + { + if (alignLeftWithPanel) + { + childPos.X = (_arrangeSize.Width - childSize.Width) / 2; + } + else if(node.AlignLeftWithNode == null) + { + childPos.X = _arrangeSize.Width - childSize.Width; + } + else + { + childPos.X = (_arrangeSize.Width + node.AlignLeftWithNode.Position.X - childSize.Width) / 2; + } + } + + if (alignBottomWithPanel) + { + if (alignTopWithPanel) + { + childPos.Y = (_arrangeSize.Height - childSize.Height) / 2; + } + else if (node.AlignTopWithNode == null) + { + childPos.Y = _arrangeSize.Height - childSize.Height; + } + else + { + childPos.Y = (_arrangeSize.Height + node.AlignLeftWithNode.Position.Y - childSize.Height) / 2; + } + } + + #endregion + + child.Arrange(new Rect(childPos.X, childPos.Y, childSize.Width, childSize.Height)); + node.Position = childPos; + node.Arranged = true; + } + } } } diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 40def187..b01bf9b2 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -91,8 +91,8 @@ - - + + diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/ColLayoutConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/ColLayoutConverter.cs index c4bbfb88..922c7a57 100644 --- a/src/Shared/HandyControl_Shared/Tools/Converter/ColLayoutConverter.cs +++ b/src/Shared/HandyControl_Shared/Tools/Converter/ColLayoutConverter.cs @@ -55,9 +55,8 @@ namespace HandyControl.Tools.Converter if (destinationType == null) throw new ArgumentNullException(nameof(destinationType)); - if (!(value is ColLayout)) throw new ArgumentException("UnexpectedParameterType"); + if (!(value is ColLayout th)) throw new ArgumentException("UnexpectedParameterType"); - var th = (ColLayout)value; if (destinationType == typeof(string)) return ToString(th, cultureInfo); if (destinationType == typeof(InstanceDescriptor)) { From bf3d33a223b197f3ccbe32068cce3599670d7ef2 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Tue, 10 Dec 2019 00:52:50 +0800 Subject: [PATCH 4/4] update readme --- README.md | 8 +- .../Controls/RelativePanelDemoCtl.xaml | 108 +++++++++--------- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index c2ae3353..62aca62e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,10 @@ Step 4:enjoy coding ## Latest examples +### RelativePanel + +![RelativePanel](https://raw.githubusercontent.com/HandyOrg/HandyOrgResource/master/HandyControl/Resources/RelativePanel.png) + ### Drawer ![Drawer](https://raw.githubusercontent.com/HandyOrg/HandyOrgResource/master/HandyControl/Resources/Drawer.gif) @@ -107,12 +111,12 @@ Step 4:enjoy coding ![GeometryAnimation](https://raw.githubusercontent.com/HandyOrg/HandyOrgResource/master/HandyControl/Resources/GeometryAnimation.gif) +## History publication + ### SplitButton ![SplitButton](https://raw.githubusercontent.com/HandyOrg/HandyOrgResource/master/HandyControl/Resources/SplitButton.png) -## History publication - ### FloatingBlock ![FloatingBlock](https://raw.githubusercontent.com/HandyOrg/HandyOrgResource/master/HandyControl/Resources/FloatingBlock.gif) diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml index d68d7060..87ca8eca 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/RelativePanelDemoCtl.xaml @@ -3,57 +3,59 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:hc="https://handyorg.github.io/handycontrol" Background="{DynamicResource RegionBrush}"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +