ComboBoxAutomationPeer.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System;
  2. using System.Collections.Generic;
  3. using Avalonia.Automation.Provider;
  4. using Avalonia.Controls;
  5. namespace Avalonia.Automation.Peers
  6. {
  7. public class ComboBoxAutomationPeer : SelectingItemsControlAutomationPeer,
  8. IExpandCollapseProvider,
  9. IValueProvider
  10. {
  11. private UnrealizedSelectionPeer[]? _selection;
  12. public ComboBoxAutomationPeer(ComboBox owner)
  13. : base(owner)
  14. {
  15. }
  16. public new ComboBox Owner => (ComboBox)base.Owner;
  17. public ExpandCollapseState ExpandCollapseState => ToState(Owner.IsDropDownOpen);
  18. public bool ShowsMenu => true;
  19. public void Collapse() => Owner.IsDropDownOpen = false;
  20. public void Expand() => Owner.IsDropDownOpen = true;
  21. bool IValueProvider.IsReadOnly => true;
  22. string? IValueProvider.Value
  23. {
  24. get
  25. {
  26. var selection = GetSelection();
  27. return selection.Count == 1 ? selection[0].GetName() : null;
  28. }
  29. }
  30. void IValueProvider.SetValue(string? value) => throw new NotSupportedException();
  31. protected override AutomationControlType GetAutomationControlTypeCore()
  32. {
  33. return AutomationControlType.ComboBox;
  34. }
  35. protected override IReadOnlyList<AutomationPeer>? GetSelectionCore()
  36. {
  37. if (ExpandCollapseState == ExpandCollapseState.Expanded)
  38. return base.GetSelectionCore();
  39. // If the combo box is not open then we won't have an ItemsPresenter so the default
  40. // GetSelectionCore implementation won't work. For this case we create a separate
  41. // peer to represent the unrealized item.
  42. if (Owner.SelectedItem is object selection)
  43. {
  44. _selection ??= new[] { new UnrealizedSelectionPeer(this) };
  45. _selection[0].Item = selection;
  46. return _selection;
  47. }
  48. return null;
  49. }
  50. protected override void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
  51. {
  52. base.OwnerPropertyChanged(sender, e);
  53. if (e.Property == ComboBox.IsDropDownOpenProperty)
  54. {
  55. RaisePropertyChangedEvent(
  56. ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty,
  57. ToState((bool)e.OldValue!),
  58. ToState((bool)e.NewValue!));
  59. }
  60. }
  61. private static ExpandCollapseState ToState(bool value)
  62. {
  63. return value ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed;
  64. }
  65. private class UnrealizedSelectionPeer : UnrealizedElementAutomationPeer
  66. {
  67. private readonly ComboBoxAutomationPeer _owner;
  68. private object? _item;
  69. public UnrealizedSelectionPeer(ComboBoxAutomationPeer owner)
  70. {
  71. _owner = owner;
  72. }
  73. public object? Item
  74. {
  75. get => _item;
  76. set
  77. {
  78. if (_item != value)
  79. {
  80. var oldValue = GetNameCore();
  81. _item = value;
  82. RaisePropertyChangedEvent(
  83. AutomationElementIdentifiers.NameProperty,
  84. oldValue,
  85. GetNameCore());
  86. }
  87. }
  88. }
  89. protected override string? GetAcceleratorKeyCore() => null;
  90. protected override string? GetAccessKeyCore() => null;
  91. protected override string? GetAutomationIdCore() => null;
  92. protected override string GetClassNameCore() => typeof(ComboBoxItem).Name;
  93. protected override AutomationPeer? GetLabeledByCore() => null;
  94. protected override AutomationPeer? GetParentCore() => _owner;
  95. protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.ListItem;
  96. protected override string? GetNameCore()
  97. {
  98. if (_item is Control c)
  99. {
  100. var result = AutomationProperties.GetName(c);
  101. if (result is null && c is ContentControl cc && cc.Presenter?.Child is TextBlock text)
  102. {
  103. result = text.Text;
  104. }
  105. if (result is null)
  106. {
  107. result = c.GetValue(ContentControl.ContentProperty)?.ToString();
  108. }
  109. return result;
  110. }
  111. return _item?.ToString();
  112. }
  113. }
  114. }
  115. }