diff --git a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
index a3c51dc965..3b4692f2aa 100644
--- a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
+++ b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
@@ -67,11 +67,7 @@ namespace Avalonia.Collections
/// The resource, or null if not found.
public TValue this[TKey key]
{
- get
- {
- return _inner[key];
- }
-
+ get => GetItemCore(key);
set
{
TValue old;
@@ -98,7 +94,11 @@ namespace Avalonia.Collections
}
}
- object IDictionary.this[object key] { get => ((IDictionary)_inner)[key]; set => ((IDictionary)_inner)[key] = value; }
+ object IDictionary.this[object key]
+ {
+ get => GetItemCore((TKey)key);
+ set => this[(TKey)key] = (TValue)value;
+ }
///
public void Add(TKey key, TValue value)
@@ -166,7 +166,7 @@ namespace Avalonia.Collections
}
///
- public bool TryGetValue(TKey key, out TValue value) => _inner.TryGetValue(key, out value);
+ public bool TryGetValue(TKey key, out TValue value) => TryGetValueCore(key, out value);
///
IEnumerator IEnumerable.GetEnumerator() => _inner.GetEnumerator();
@@ -204,6 +204,9 @@ namespace Avalonia.Collections
///
void IDictionary.Remove(object key) => Remove((TKey)key);
+ protected virtual TValue GetItemCore(TKey key) => _inner[key];
+ protected virtual bool TryGetValueCore(TKey key, out TValue value) => _inner.TryGetValue(key, out value);
+
private void NotifyAdd(TKey key, TValue value)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
diff --git a/src/Avalonia.Build.Tasks/Properties/launchSettings.json b/src/Avalonia.Build.Tasks/Properties/launchSettings.json
new file mode 100644
index 0000000000..6f880e9b85
--- /dev/null
+++ b/src/Avalonia.Build.Tasks/Properties/launchSettings.json
@@ -0,0 +1,9 @@
+{
+ "profiles": {
+ "Avalonia.Build.Tasks": {
+ "commandName": "Executable",
+ "executablePath": "$(SolutionDir)\\src\\Avalonia.Build.Tasks\\bin\\Debug\\netcoreapp3.1\\Avalonia.Build.Tasks.exe",
+ "commandLineArgs": "D:\\projects\\AvaloniaUI\\Avalonia\\src\\Avalonia.Themes.Fluent\\obj\\Debug\\netstandard2.0\\Avalonia\\original.dll \"D:\\projects\\AvaloniaUI\\Avalonia\\src\\Avalonia.Themes.Fluent\\obj\\Debug\\netstandard2.0\\Avalonia\\references\" $(SolutionDir)\\out.dll"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Controls/Templates/IControlTemplate.cs b/src/Avalonia.Controls/Templates/IControlTemplate.cs
index af5f3097af..3f64632087 100644
--- a/src/Avalonia.Controls/Templates/IControlTemplate.cs
+++ b/src/Avalonia.Controls/Templates/IControlTemplate.cs
@@ -9,22 +9,4 @@ namespace Avalonia.Controls.Templates
public interface IControlTemplate : ITemplate>
{
}
-
- public class TemplateResult
- {
- public T Result { get; }
- public INameScope NameScope { get; }
-
- public TemplateResult(T result, INameScope nameScope)
- {
- Result = result;
- NameScope = nameScope;
- }
-
- public void Deconstruct(out T result, out INameScope scope)
- {
- result = Result;
- scope = NameScope;
- }
- }
}
diff --git a/src/Avalonia.Styling/Controls/ResourceDictionary.cs b/src/Avalonia.Styling/Controls/ResourceDictionary.cs
index c56dd74143..c19e975950 100644
--- a/src/Avalonia.Styling/Controls/ResourceDictionary.cs
+++ b/src/Avalonia.Styling/Controls/ResourceDictionary.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Collections;
-using Avalonia.Metadata;
+using Avalonia.Controls.Templates;
#nullable enable
@@ -101,6 +101,11 @@ namespace Avalonia.Controls
public event EventHandler? OwnerChanged;
+ public void Add(object key, Func loader)
+ {
+ Add(key, new LazyItem(loader));
+ }
+
public bool TryGetResource(object key, out object? value)
{
if (TryGetValue(key, out value))
@@ -176,9 +181,52 @@ namespace Avalonia.Controls
}
}
+ protected override object? GetItemCore(object key)
+ {
+ var item = base.GetItemCore(key);
+
+ if (item is LazyItem lazy)
+ {
+ var value = lazy.Load();
+ this[key] = value;
+ return value;
+ }
+ else
+ {
+ return item;
+ }
+ }
+
+ protected override bool TryGetValueCore(object key, out object? value)
+ {
+ if (base.TryGetValueCore(key, out value))
+ {
+ if (value is LazyItem lazy)
+ {
+ value = lazy.Load();
+ this[key] = value;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
}
+
+ private class LazyItem
+ {
+ private Func _load;
+ public LazyItem(Func load) => _load = load;
+ public object? Load()
+ {
+ var result = _load(null);
+ return result is TemplateResult