using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Markup; using System.Windows.Media.Effects; namespace HandyControl.Controls; [DefaultProperty("Content")] [ContentProperty("Content")] public class BlendEffectBox : Control { private readonly ContentPresenter _effectBottomPresenter; private readonly ContentPresenter _effectTopPresenter; private bool _isInternalAction; public BlendEffectBox() { _effectTopPresenter = new ContentPresenter(); ActualContent = _effectTopPresenter; _effectBottomPresenter = new ContentPresenter(); _effectBottomPresenter.SetBinding(ContentPresenter.ContentProperty, new Binding(ContentProperty.Name) { Source = this }); var effects = new ObservableCollection(); effects.CollectionChanged += OnEffectsChanged; Effects = effects; } private void OnEffectsChanged(object sender, NotifyCollectionChangedEventArgs e) { if (Effects == null || Effects.Count == 0) { ClearEffect(_effectTopPresenter); return; } if (_isInternalAction) return; _isInternalAction = true; AddEffect(_effectTopPresenter, Effects.Count); _isInternalAction = false; } private void ClearEffect(ContentPresenter presenter) { if (presenter == null) return; if (ReferenceEquals(_effectBottomPresenter, presenter)) { _effectBottomPresenter.SetCurrentValue(EffectProperty, null); return; } presenter.SetCurrentValue(EffectProperty, null); ClearEffect(presenter.Content as ContentPresenter); } private void AddEffect(ContentPresenter presenter, int count) { var newCount = --count; if (newCount >= 0) { presenter.Effect = Effects[newCount]; var nextCount = --count; if (nextCount >= 1) { var content = new ContentPresenter(); presenter.Content = content; AddEffect(content, newCount); } else if (nextCount >= 0) { _effectBottomPresenter.Effect = Effects[0]; presenter.Content = _effectBottomPresenter; } else { presenter.Content = _effectBottomPresenter; } } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Bindable(true)] public Collection Effects { get; } public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( nameof(Content), typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement))); public FrameworkElement Content { get => (FrameworkElement) GetValue(ContentProperty); set => SetValue(ContentProperty, value); } internal static readonly DependencyProperty ActualContentProperty = DependencyProperty.Register( nameof(ActualContent), typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement))); internal FrameworkElement ActualContent { get => (FrameworkElement) GetValue(ActualContentProperty); set => SetValue(ActualContentProperty, value); } }