BlendEffectBox.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System.Collections.ObjectModel;
  2. using System.Collections.Specialized;
  3. using System.ComponentModel;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Data;
  7. using System.Windows.Markup;
  8. using System.Windows.Media.Effects;
  9. namespace HandyControl.Controls;
  10. [DefaultProperty("Content")]
  11. [ContentProperty("Content")]
  12. public class BlendEffectBox : Control
  13. {
  14. private readonly ContentPresenter _effectBottomPresenter;
  15. private readonly ContentPresenter _effectTopPresenter;
  16. private bool _isInternalAction;
  17. public BlendEffectBox()
  18. {
  19. _effectTopPresenter = new ContentPresenter();
  20. ActualContent = _effectTopPresenter;
  21. _effectBottomPresenter = new ContentPresenter();
  22. _effectBottomPresenter.SetBinding(ContentPresenter.ContentProperty, new Binding(ContentProperty.Name)
  23. {
  24. Source = this
  25. });
  26. var effects = new ObservableCollection<Effect>();
  27. effects.CollectionChanged += OnEffectsChanged;
  28. Effects = effects;
  29. }
  30. private void OnEffectsChanged(object sender, NotifyCollectionChangedEventArgs e)
  31. {
  32. if (Effects == null || Effects.Count == 0)
  33. {
  34. ClearEffect(_effectTopPresenter);
  35. return;
  36. }
  37. if (_isInternalAction) return;
  38. _isInternalAction = true;
  39. AddEffect(_effectTopPresenter, Effects.Count);
  40. _isInternalAction = false;
  41. }
  42. private void ClearEffect(ContentPresenter presenter)
  43. {
  44. if (presenter == null) return;
  45. if (ReferenceEquals(_effectBottomPresenter, presenter))
  46. {
  47. _effectBottomPresenter.SetCurrentValue(EffectProperty, null);
  48. return;
  49. }
  50. presenter.SetCurrentValue(EffectProperty, null);
  51. ClearEffect(presenter.Content as ContentPresenter);
  52. }
  53. private void AddEffect(ContentPresenter presenter, int count)
  54. {
  55. var newCount = --count;
  56. if (newCount >= 0)
  57. {
  58. presenter.Effect = Effects[newCount];
  59. var nextCount = --count;
  60. if (nextCount >= 1)
  61. {
  62. var content = new ContentPresenter();
  63. presenter.Content = content;
  64. AddEffect(content, newCount);
  65. }
  66. else if (nextCount >= 0)
  67. {
  68. _effectBottomPresenter.Effect = Effects[0];
  69. presenter.Content = _effectBottomPresenter;
  70. }
  71. else
  72. {
  73. presenter.Content = _effectBottomPresenter;
  74. }
  75. }
  76. }
  77. [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  78. [Bindable(true)]
  79. public Collection<Effect> Effects { get; }
  80. public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
  81. nameof(Content), typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
  82. public FrameworkElement Content
  83. {
  84. get => (FrameworkElement) GetValue(ContentProperty);
  85. set => SetValue(ContentProperty, value);
  86. }
  87. internal static readonly DependencyProperty ActualContentProperty = DependencyProperty.Register(
  88. nameof(ActualContent), typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
  89. internal FrameworkElement ActualContent
  90. {
  91. get => (FrameworkElement) GetValue(ActualContentProperty);
  92. set => SetValue(ActualContentProperty, value);
  93. }
  94. }