ResourceDictionary.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.Specialized;
  6. using System.Linq;
  7. using Avalonia.Collections;
  8. namespace Avalonia.Controls
  9. {
  10. /// <summary>
  11. /// An indexed dictionary of resources.
  12. /// </summary>
  13. public class ResourceDictionary : AvaloniaDictionary<object, object>, IResourceDictionary
  14. {
  15. private AvaloniaList<IResourceProvider> _mergedDictionaries;
  16. /// <summary>
  17. /// Initializes a new instance of the <see cref="ResourceDictionary"/> class.
  18. /// </summary>
  19. public ResourceDictionary()
  20. {
  21. CollectionChanged += OnCollectionChanged;
  22. }
  23. /// <inheritdoc/>
  24. public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged;
  25. /// <inheritdoc/>
  26. public IList<IResourceProvider> MergedDictionaries
  27. {
  28. get
  29. {
  30. if (_mergedDictionaries == null)
  31. {
  32. _mergedDictionaries = new AvaloniaList<IResourceProvider>();
  33. _mergedDictionaries.ResetBehavior = ResetBehavior.Remove;
  34. _mergedDictionaries.ForEachItem(
  35. x =>
  36. {
  37. if (x.HasResources)
  38. {
  39. OnResourcesChanged();
  40. }
  41. x.ResourcesChanged += MergedDictionaryResourcesChanged;
  42. },
  43. x =>
  44. {
  45. if (x.HasResources)
  46. {
  47. OnResourcesChanged();
  48. }
  49. x.ResourcesChanged -= MergedDictionaryResourcesChanged;
  50. },
  51. () => { });
  52. }
  53. return _mergedDictionaries;
  54. }
  55. }
  56. /// <inheritdoc/>
  57. bool IResourceProvider.HasResources
  58. {
  59. get => Count > 0 || (_mergedDictionaries?.Any(x => x.HasResources) ?? false);
  60. }
  61. /// <inheritdoc/>
  62. public bool TryGetResource(string key, out object value)
  63. {
  64. if (TryGetValue(key, out value))
  65. {
  66. return true;
  67. }
  68. if (_mergedDictionaries != null)
  69. {
  70. for (var i = _mergedDictionaries.Count - 1; i >= 0; --i)
  71. {
  72. if (_mergedDictionaries[i].TryGetResource(key, out value))
  73. {
  74. return true;
  75. }
  76. }
  77. }
  78. return false;
  79. }
  80. private void OnResourcesChanged()
  81. {
  82. ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs());
  83. }
  84. private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) => OnResourcesChanged();
  85. private void MergedDictionaryResourcesChanged(object sender, ResourcesChangedEventArgs e) => OnResourcesChanged();
  86. }
  87. }