Skip to content

Commit

Permalink
fix: Allow multiple default value providers
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Jun 4, 2021
1 parent 540091f commit d39362b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/DependencyPropertyDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private bool SetValueFast(object? value, DependencyPropertyValuePrecedences prec
return false;
}

internal void SetDefaultValue(object defaultValue)
internal void SetDefaultValue(object? defaultValue)
{
_defaultValue = defaultValue;
_flags |= Flags.DefaultValueSet;
Expand Down
45 changes: 39 additions & 6 deletions src/Uno.UI/UI/Xaml/DependencyPropertyDetailsCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ partial class DependencyPropertyDetailsCollection : IDisposable
private int _entriesLength;
private int _minId;
private int _maxId;
private DependencyObjectStore.DefaultValueProvider? _defaultValueProvider;
private List<DependencyObjectStore.DefaultValueProvider>? _defaultValueProviders = null;

private object? Owner => _hardOwnerReference ?? _ownerReference.Target;

Expand Down Expand Up @@ -141,9 +141,9 @@ public DependencyPropertyDetails FindPropertyDetails(DependencyProperty property
{
propertyEntry = new DependencyPropertyDetails(property, _ownerType);

if(_defaultValueProvider != null && _defaultValueProvider(property, out var v))
if (TryResolveDefaultValueFromProviders(property, out var value))
{
propertyEntry.SetDefaultValue(v);
propertyEntry.SetDefaultValue(value);
}
}

Expand Down Expand Up @@ -178,9 +178,9 @@ public DependencyPropertyDetails FindPropertyDetails(DependencyProperty property

ref var propertyEntry = ref Entries![property.UniqueId - _minId];
propertyEntry = new DependencyPropertyDetails(property, _ownerType);
if (_defaultValueProvider != null && _defaultValueProvider(property, out var v))
if (TryResolveDefaultValueFromProviders(property, out var value))
{
propertyEntry.SetValue(v, DependencyPropertyValuePrecedences.DefaultValue);
propertyEntry.SetValue(value, DependencyPropertyValuePrecedences.DefaultValue);
}

return propertyEntry;
Expand All @@ -192,6 +192,24 @@ public DependencyPropertyDetails FindPropertyDetails(DependencyProperty property
}
}

private bool TryResolveDefaultValueFromProviders(DependencyProperty property, out object? value)
{
if (_defaultValueProviders != null)
{
for (int i = _defaultValueProviders.Count - 1; i >= 0; i--)
{
var provider = _defaultValueProviders[i];
if (provider.Invoke(property, out var resolvedValue))
{
value = resolvedValue;
return true;
}
}
}
value = null;
return false;
}

private void AssignEntries(DependencyPropertyDetails[] newEntries, int newSize)
{
ReturnEntriesToPool();
Expand All @@ -214,9 +232,24 @@ private void ReturnEntriesToPool()

internal IEnumerable<DependencyPropertyDetails> GetAllDetails() => Entries.Trim();

/// <summary>
/// Adds a default value provider.
/// </summary>
/// <param name="provider">Default value provider.</param>
/// <remarks>
/// Providers which are registered later have higher precedence.
/// E.g. when both a derived and base class register their own default
/// value provider in the constructor for the same property, the derived
/// class value is used.
/// </remarks>
public void RegisterDefaultValueProvider(DependencyObjectStore.DefaultValueProvider provider)
{
_defaultValueProvider = provider;
if (_defaultValueProviders == null)
{
_defaultValueProviders = new List<DependencyObjectStore.DefaultValueProvider>();
}

_defaultValueProviders.Add(provider);
}

internal void TryEnableHardReferences()
Expand Down

0 comments on commit d39362b

Please sign in to comment.