BoundsObserverBehavior.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using System.Reactive;
  2. using System.Reactive.Disposables;
  3. using Avalonia.Controls;
  4. using Avalonia.Data;
  5. namespace Avalonia.Xaml.Interactions.Custom;
  6. /// <summary>
  7. /// Observes the bounds of an associated <see cref="Control"/> and updates its Width and Height properties.
  8. /// </summary>
  9. public class BoundsObserverBehavior : DisposingBehavior<Control>
  10. {
  11. /// <summary>
  12. /// Defines the <see cref="Bounds"/> property.
  13. /// </summary>
  14. public static readonly StyledProperty<Rect> BoundsProperty =
  15. AvaloniaProperty.Register<BoundsObserverBehavior, Rect>(nameof(Bounds), defaultBindingMode: BindingMode.OneWay);
  16. /// <summary>
  17. /// Defines the <see cref="Width"/> property.
  18. /// </summary>
  19. public static readonly StyledProperty<double> WidthProperty =
  20. AvaloniaProperty.Register<BoundsObserverBehavior, double>(nameof(Width),
  21. defaultBindingMode: BindingMode.TwoWay);
  22. /// <summary>
  23. /// Defines the <see cref="Height"/> property.
  24. /// </summary>
  25. public static readonly StyledProperty<double> HeightProperty =
  26. AvaloniaProperty.Register<BoundsObserverBehavior, double>(nameof(Height),
  27. defaultBindingMode: BindingMode.TwoWay);
  28. /// <summary>
  29. /// Gets or sets the bounds of the associated control. This is a styled Avalonia property.
  30. /// </summary>
  31. public Rect Bounds
  32. {
  33. get => GetValue(BoundsProperty);
  34. set => SetValue(BoundsProperty, value);
  35. }
  36. /// <summary>
  37. /// Gets or sets the width of the associated control. This is a two-way bound Avalonia property.
  38. /// </summary>
  39. public double Width
  40. {
  41. get => GetValue(WidthProperty);
  42. set => SetValue(WidthProperty, value);
  43. }
  44. /// <summary>
  45. /// Gets or sets the height of the associated control. This is a two-way bound Avalonia property.
  46. /// </summary>
  47. public double Height
  48. {
  49. get => GetValue(HeightProperty);
  50. set => SetValue(HeightProperty, value);
  51. }
  52. /// <summary>
  53. /// Attaches the behavior to the associated control and starts observing its bounds to update the Width and Height properties accordingly.
  54. /// </summary>
  55. /// <param name="disposables">A composite disposable used to manage the lifecycle of subscriptions and other disposables.</param>
  56. protected override void OnAttached(CompositeDisposable disposables)
  57. {
  58. if (AssociatedObject is not null)
  59. {
  60. disposables.Add(this.GetObservable(BoundsProperty)
  61. .Subscribe(new AnonymousObserver<Rect>(bounds =>
  62. {
  63. Width = bounds.Width;
  64. Height = bounds.Height;
  65. })));
  66. }
  67. }
  68. }