Skip to content

Commit

Permalink
A helper method to simplify creating dependency properties on all pla…
Browse files Browse the repository at this point in the history
…tforms (#568)

* Create a simpler way to create dependency properties on all platforms
  • Loading branch information
dotMorten committed Apr 17, 2024
1 parent 28eca23 commit cb35cbd
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 83 deletions.
50 changes: 50 additions & 0 deletions src/Toolkit/Toolkit/Internal/PropertyHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// /*******************************************************************************
// * Copyright 2012-2018 Esri
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// ******************************************************************************/


#if MAUI
global using DependencyProperty = Microsoft.Maui.Controls.BindableProperty;
using DependencyObject = Microsoft.Maui.Controls.BindableObject;
#endif
namespace Esri.ArcGISRuntime.Toolkit.Internal
{
internal static class PropertyHelper
{
/// <summary>
/// Abstracts away the different syntax for declaring a dependency property in MAUI, UWP, WinUI and WPF
/// </summary>
/// <typeparam name="ValueType">The property type</typeparam>
/// <typeparam name="OwnerType">The type this dependency property is declared on (ie the owner)</typeparam>
/// <param name="propertyName">Name of the property</param>
/// <param name="defaultValue">The default value</param>
/// <param name="propertyChanged">Method to call when value changes</param>
/// <returns></returns>
public static DependencyProperty CreateProperty<ValueType, OwnerType>(string propertyName,
ValueType? defaultValue = default,
Action<OwnerType, ValueType?, ValueType?>? propertyChanged = null) where OwnerType : DependencyObject
#if MAUI
=> DependencyProperty.Create(propertyName, typeof(ValueType), typeof(OwnerType), defaultValue, propertyChanged: propertyChanged is null ? null :
(s, oldValue, newValue) => propertyChanged?.Invoke((OwnerType)s, oldValue is null ? default : (ValueType)oldValue, newValue is null ? default : (ValueType)newValue));
#else
=> DependencyProperty.Register(propertyName, typeof(ValueType), typeof(OwnerType),
new PropertyMetadata(defaultValue,
propertyChanged is null ? null :
(s, e) => propertyChanged?.Invoke((OwnerType)s, e.OldValue is null ? default : (ValueType)e.OldValue, e.NewValue is null ? default : (ValueType)e.NewValue)));
#endif
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#if MAUI
using Esri.ArcGISRuntime.Toolkit.Maui;
using TextBlock = Microsoft.Maui.Controls.Label;
using DependencyProperty = Microsoft.Maui.Controls.BindableProperty;
#else
using Esri.ArcGISRuntime.Toolkit.UI.Controls;
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#if WPF || MAUI
using Esri.ArcGISRuntime.Mapping.Popups;
using Esri.ArcGISRuntime.Toolkit.Internal;
using Microsoft.Win32;
#if WPF
using System.Windows.Controls.Primitives;
Expand Down Expand Up @@ -123,13 +124,8 @@ private async void LoadAttachments()
/// <summary>
/// Identifies the <see cref="Element"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty ElementProperty =
BindableProperty.Create(nameof(Element), typeof(AttachmentsPopupElement), typeof(AttachmentsPopupElementView), null, propertyChanged: (s, o, n) => ((AttachmentsPopupElementView)s).LoadAttachments());
#else
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register(nameof(Element), typeof(AttachmentsPopupElement), typeof(AttachmentsPopupElementView), new PropertyMetadata(null, (s, e) => ((AttachmentsPopupElementView)s).LoadAttachments()));
#endif
PropertyHelper.CreateProperty<AttachmentsPopupElement, AttachmentsPopupElementView>(nameof(Element), null, (s, oldValue, newValue) => s.LoadAttachments());
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,8 @@ public override void OnApplyTemplate()
/// <summary>
/// Identifies the <see cref="Element"/> dependency property.
/// </summary>

#if MAUI
public static readonly BindableProperty ElementProperty =
BindableProperty.Create(nameof(Element), typeof(FieldsPopupElement), typeof(FieldsPopupElementView), null, propertyChanged: (s, o, n) => ((FieldsPopupElementView)s).RefreshTable());
#else
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register(nameof(Element), typeof(FieldsPopupElement), typeof(FieldsPopupElementView), new PropertyMetadata(null, (s, e) => ((FieldsPopupElementView)s).RefreshTable()));
#endif
PropertyHelper.CreateProperty<AttachmentsPopupElement, FieldsPopupElementView>(nameof(Element), null, (s, oldValue, newValue) => s.RefreshTable());

private void RefreshTable()
{
Expand Down Expand Up @@ -191,13 +185,8 @@ public Brush RowOddBackground
/// <summary>
/// Identifies the <see cref="RowOddBackground"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty RowOddBackgroundProperty =
BindableProperty.Create(nameof(RowOddBackground), typeof(Brush), typeof(FieldsPopupElementView), null);
#else
public static readonly DependencyProperty RowOddBackgroundProperty =
DependencyProperty.Register(nameof(RowOddBackground), typeof(Brush), typeof(FieldsPopupElementView), new PropertyMetadata(null));
#endif
PropertyHelper.CreateProperty<Brush, FieldsPopupElementView>(nameof(RowOddBackground));

/// <summary>
/// Gets or sets the background of the even rows in the table.
Expand All @@ -211,13 +200,8 @@ public Brush RowEvenBackground
/// <summary>
/// Identifies the <see cref="RowEvenBackground"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty RowEvenBackgroundProperty =
BindableProperty.Create(nameof(RowEvenBackground), typeof(Brush), typeof(FieldsPopupElementView), null);
#else
public static readonly DependencyProperty RowEvenBackgroundProperty =
DependencyProperty.Register(nameof(RowEvenBackground), typeof(Brush), typeof(FieldsPopupElementView), new PropertyMetadata(null));
#endif
PropertyHelper.CreateProperty<Brush, FieldsPopupElementView>(nameof(RowEvenBackground));

/// <summary>
/// Gets or sets the vertical divider brush in the table.
Expand All @@ -231,13 +215,8 @@ public Brush DividerBrush
/// <summary>
/// Identifies the <see cref="DividerBrush"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty DividerBrushProperty =
BindableProperty.Create(nameof(DividerBrush), typeof(Brush), typeof(FieldsPopupElementView), null);
#else
public static readonly DependencyProperty DividerBrushProperty =
DependencyProperty.Register(nameof(DividerBrush), typeof(Brush), typeof(FieldsPopupElementView), new PropertyMetadata(null));
#endif
PropertyHelper.CreateProperty<Brush, FieldsPopupElementView>(nameof(DividerBrush));

/// <summary>
/// Gets or sets the <see cref="TextBlock"/> style applied to the text in the table.
Expand All @@ -251,13 +230,8 @@ public Style FieldTextStyle
/// <summary>
/// Identifies the <see cref="FieldTextStyle"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty FieldTextStyleProperty =
BindableProperty.Create(nameof(FieldTextStyle), typeof(Style), typeof(FieldsPopupElementView), null);
#else
public static readonly DependencyProperty FieldTextStyleProperty =
DependencyProperty.Register(nameof(FieldTextStyle), typeof(Style), typeof(FieldsPopupElementView), new PropertyMetadata(null));
#endif
PropertyHelper.CreateProperty<Style, FieldsPopupElementView>(nameof(FieldTextStyle));
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#if WPF || MAUI

using Esri.ArcGISRuntime.Mapping.Popups;
using Esri.ArcGISRuntime.Toolkit.Internal;
using System.Collections;

#if MAUI
Expand Down Expand Up @@ -50,13 +51,8 @@ public MediaPopupElementView()
/// <summary>
/// Identifies the <see cref="Element"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty ElementProperty =
BindableProperty.Create(nameof(Element), typeof(MediaPopupElement), typeof(MediaPopupElementView), null, propertyChanged: (s, o, n) => ((MediaPopupElementView)s).OnElementPropertyChanged());
#else
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register(nameof(Element), typeof(MediaPopupElement), typeof(MediaPopupElementView), new PropertyMetadata(null, (s, e) => ((MediaPopupElementView)s).OnElementPropertyChanged()));
#endif
PropertyHelper.CreateProperty<MediaPopupElement, MediaPopupElementView>(nameof(Element), null, (s, oldValue, newValue) => s.OnElementPropertyChanged());
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,8 @@ private async void UpdateChart(Size desiredSize)
/// <summary>
/// Identifies the <see cref="PopupMedia"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty PopupMediaProperty =
BindableProperty.Create(nameof(PopupMedia), typeof(PopupMedia), typeof(PopupMediaView), null, propertyChanged: (s, o, n) => ((PopupMediaView)s).OnPopupMediaPropertyChanged());
#else
public static readonly DependencyProperty PopupMediaProperty =
DependencyProperty.Register(nameof(PopupMedia), typeof(PopupMedia), typeof(PopupMediaView), new PropertyMetadata(null, (s, e) => ((PopupMediaView)s).OnPopupMediaPropertyChanged()));
#endif
PropertyHelper.CreateProperty<PopupMedia, PopupMediaView>(nameof(PopupMedia), null, (s, oldValue, newValue) => s.OnPopupMediaPropertyChanged());

private void OnPopupMediaPropertyChanged()
{
Expand Down
44 changes: 18 additions & 26 deletions src/Toolkit/Toolkit/UI/Controls/PopupViewer/PopupViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,54 +155,45 @@ private void InvalidatePopup()
/// <summary>
/// Identifies the <see cref="PopupManager"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty PopupProperty =
BindableProperty.Create(nameof(Popup), typeof(Popup), typeof(PopupViewer), null, propertyChanged: OnPopupPropertyChanged);
#else
public static readonly DependencyProperty PopupProperty =
DependencyProperty.Register(nameof(Popup), typeof(Popup), typeof(PopupViewer),
new PropertyMetadata(null, (s,e) => PopupViewer.OnPopupPropertyChanged(s, e.OldValue, e.NewValue)));
#endif
PropertyHelper.CreateProperty<Popup, PopupViewer>(nameof(Popup), null, (s, oldValue, newValue) => s.OnPopupPropertyChanged(oldValue, newValue));

private static void OnPopupPropertyChanged(DependencyObject d, object oldValue, object newValue)
private void OnPopupPropertyChanged(Popup? oldPopup, Popup? newPopup)
{
var popupViewer = (PopupViewer)d;
var oldPopup = oldValue as Popup;
if (oldPopup?.GeoElement is not null)
{
popupViewer._dynamicEntityChangedListener?.Detach();
popupViewer._dynamicEntityChangedListener = null;
popupViewer._geoElementPropertyChangedListener?.Detach();
popupViewer._geoElementPropertyChangedListener = null;
_dynamicEntityChangedListener?.Detach();
_dynamicEntityChangedListener = null;
_geoElementPropertyChangedListener?.Detach();
_geoElementPropertyChangedListener = null;
}
var newPopup = newValue as Popup;
if (newPopup?.GeoElement is not null)
{
if(newPopup.GeoElement is DynamicEntity de)
{
popupViewer._dynamicEntityChangedListener = new WeakEventListener<PopupViewer, DynamicEntity, object?, DynamicEntityChangedEventArgs>(popupViewer, de)
_dynamicEntityChangedListener = new WeakEventListener<PopupViewer, DynamicEntity, object?, DynamicEntityChangedEventArgs>(this, de)
{
OnEventAction = static (instance, source, eventArgs) => instance.InvalidatePopup(),
OnDetachAction = static (instance, source, weakEventListener) => source.DynamicEntityChanged -= weakEventListener.OnEvent,
};
de.DynamicEntityChanged += popupViewer._dynamicEntityChangedListener.OnEvent;
de.DynamicEntityChanged += _dynamicEntityChangedListener.OnEvent;
}
else if (newPopup.GeoElement is INotifyPropertyChanged inpc)
{
popupViewer._geoElementPropertyChangedListener = new WeakEventListener<PopupViewer, INotifyPropertyChanged, object?, PropertyChangedEventArgs>(popupViewer, inpc)
_geoElementPropertyChangedListener = new WeakEventListener<PopupViewer, INotifyPropertyChanged, object?, PropertyChangedEventArgs>(this, inpc)
{
OnEventAction = static (instance, source, eventArgs) => instance.InvalidatePopup(),
OnDetachAction = static (instance, source, weakEventListener) => source.PropertyChanged -= weakEventListener.OnEvent,
};
inpc.PropertyChanged += popupViewer._geoElementPropertyChangedListener.OnEvent;
inpc.PropertyChanged += _geoElementPropertyChangedListener.OnEvent;

}
}
popupViewer.InvalidatePopup();
InvalidatePopup();
#if MAUI
(popupViewer.GetTemplateChild(PopupContentScrollViewerName) as ScrollViewer)?.ScrollToAsync(0,0,false);
(GetTemplateChild(PopupContentScrollViewerName) as ScrollViewer)?.ScrollToAsync(0,0,false);
#else
(popupViewer.GetTemplateChild(PopupContentScrollViewerName) as ScrollViewer)?.ScrollToHome();
(GetTemplateChild(PopupContentScrollViewerName) as ScrollViewer)?.ScrollToHome();
#endif
}

Expand All @@ -218,13 +209,14 @@ public ScrollBarVisibility VerticalScrollBarVisibility
/// <summary>
/// Identifies the <see cref="VerticalScrollBarVisibility"/> dependency property.
/// </summary>
public static readonly DependencyProperty VerticalScrollBarVisibilityProperty =
PropertyHelper.CreateProperty<ScrollBarVisibility, PopupViewer>(nameof(VerticalScrollBarVisibility),
#if MAUI
public static readonly BindableProperty VerticalScrollBarVisibilityProperty =
BindableProperty.Create(nameof(VerticalScrollBarVisibility), typeof(ScrollBarVisibility), typeof(PopupViewer), ScrollBarVisibility.Default);
ScrollBarVisibility.Default
#else
public static readonly DependencyProperty VerticalScrollBarVisibilityProperty =
DependencyProperty.Register(nameof(VerticalScrollBarVisibility), typeof(ScrollBarVisibility), typeof(PopupViewer), new PropertyMetadata(ScrollBarVisibility.Auto));
ScrollBarVisibility.Auto
#endif
);
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,8 @@ public override void OnApplyTemplate()
/// <summary>
/// Identifies the <see cref="Element"/> dependency property.
/// </summary>
#if MAUI
public static readonly BindableProperty ElementProperty =
BindableProperty.Create(nameof(Element), typeof(TextPopupElement), typeof(TextPopupElementView), null, propertyChanged: (s,o,n) => ((TextPopupElementView)s).OnElementPropertyChanged());
#else
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register(nameof(Element), typeof(TextPopupElement), typeof(TextPopupElementView), new PropertyMetadata(null, (s, e) => ((TextPopupElementView)s).OnElementPropertyChanged()));
#endif

PropertyHelper.CreateProperty<TextPopupElement, TextPopupElementView>(nameof(Element), null, (s, oldValue, newValue) => s.OnElementPropertyChanged());
}
}
#endif

0 comments on commit cb35cbd

Please sign in to comment.