diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListView.ListViewAccessibleObject.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListView.ListViewAccessibleObject.cs index 203e1a988cb..9b14964f3ab 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListView.ListViewAccessibleObject.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListView.ListViewAccessibleObject.cs @@ -179,6 +179,22 @@ private string GetItemStatus() => this.TryGetOwnerAs(out ListView? owningListVie return columnHeaders; } + internal override IRawElementProviderSimple.Interface? GetItem(int row, int column) + { + if (!this.TryGetOwnerAs(out ListView? owningListView) + || owningListView.View != View.Details + || row < 0 + || row >= owningListView.Items.Count + || column < 0 + || column >= owningListView.Columns.Count + || owningListView.Items[row].AccessibilityObject is not ListViewItem.ListViewItemDetailsAccessibleObject itemAccessibleObject) + { + return null; + } + + return itemAccessibleObject.GetChild(column + itemAccessibleObject.FirstSubItemIndex); + } + internal override IRawElementProviderFragment.Interface? GetFocus() => !this.IsOwnerHandleCreated(out ListView? owningListView) ? null diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListViewItem.ListViewItemDetailsAccessibleObject.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListViewItem.ListViewItemDetailsAccessibleObject.cs index 39b70bc3f27..806bc49f270 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListViewItem.ListViewItemDetailsAccessibleObject.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ListView/ListViewItem.ListViewItemDetailsAccessibleObject.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; +using System.Text; using Windows.Win32.UI.Accessibility; namespace System.Windows.Forms; @@ -22,6 +23,38 @@ public ListViewItemDetailsAccessibleObject(ListViewItem owningItem) : base(ownin private int LastChildIndex => HasImage ? _owningListView.Columns.Count : _owningListView.Columns.Count - 1; + public override string? Name + { + get + { + if (!_owningListView.FullRowSelect + || !_owningListView.SupportsListViewSubItems + || _owningListView.Columns.Count == 0) + { + return base.Name; + } + + StringBuilder name = new(); + for (int columnIndex = 0; columnIndex < _owningListView.Columns.Count; columnIndex++) + { + int subItemIndex = _owningListView.Columns[columnIndex]._correspondingListViewSubItemIndex; + if (subItemIndex < 0 || subItemIndex >= _owningItem.SubItems.Count) + { + continue; + } + + if (name.Length > 0) + { + name.Append(", "); + } + + name.Append(_owningItem.SubItems[subItemIndex].AccessibilityObject?.Name); + } + + return name.Length > 0 ? name.ToString() : base.Name; + } + } + protected override View View => View.Details; /// diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListVIew.ListViewAccessibleObjectTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListVIew.ListViewAccessibleObjectTests.cs index fc4f8de3011..242d6aa2059 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListVIew.ListViewAccessibleObjectTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListVIew.ListViewAccessibleObjectTests.cs @@ -202,6 +202,38 @@ public void ListViewAccessibleObject_EmptyList_GetChild_ReturnsCorrectValue() Assert.False(listView.IsHandleCreated); } + [WinFormsTheory] + [InlineData(false)] + [InlineData(true)] + public void ListViewAccessibleObject_GetItem_DetailsView_ReturnsSubItem(bool hasImage) + { + using ImageList imageList = new(); + imageList.Images.Add(Form.DefaultIcon); + using ListView listView = new() + { + SmallImageList = imageList, + View = View.Details + }; + + listView.Columns.AddRange((ColumnHeader[])[new("Title"), new("Position")]); + ListViewItem item = new(["Item 1", "Position 1"], hasImage ? 0 : -1); + listView.Items.Add(item); + listView.CreateControl(); + + AccessibleObject actual = (AccessibleObject)listView.AccessibilityObject.GetItem(0, 1); + + Assert.Same(item.SubItems[1].AccessibilityObject, actual); + Assert.Equal("Position 1", actual.Name); + Assert.Equal( + UIA_CONTROLTYPE_ID.UIA_TextControlTypeId, + (UIA_CONTROLTYPE_ID)(int)actual.GetPropertyValue(UIA_PROPERTY_ID.UIA_ControlTypePropertyId)); + Assert.Null(listView.AccessibilityObject.GetItem(-1, 0)); + Assert.Null(listView.AccessibilityObject.GetItem(0, -1)); + Assert.Null(listView.AccessibilityObject.GetItem(1, 0)); + Assert.Null(listView.AccessibilityObject.GetItem(0, 2)); + Assert.True(listView.IsHandleCreated); + } + [WinFormsFact] public void ListViewAccessibleObject_GetPropertyValue_returns_correct_values() { diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListViewItem.ListViewItemDetailsAccessibleObjectTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListViewItem.ListViewItemDetailsAccessibleObjectTests.cs index 1cabcda2db6..53e7ff3c445 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListViewItem.ListViewItemDetailsAccessibleObjectTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/AccessibleObjects/ListViewItem.ListViewItemDetailsAccessibleObjectTests.cs @@ -17,6 +17,42 @@ public void ListViewItemDetailsAccessibleObject_Ctor_OwnerListViewItemCannotBeNu Assert.Throws(() => new ListViewItemDetailsAccessibleObject(null)); } + [WinFormsFact] + public void ListViewItemDetailsAccessibleObject_Name_FullRowSelect_ReturnsAllColumnValues() + { + using ListView control = new() + { + FullRowSelect = true, + View = View.Details + }; + + control.Columns.AddRange((ColumnHeader[])[new(), new(), new()]); + ListViewItem item = new(["Item", "Value 1", "Value 2"]); + control.Items.Add(item); + + AccessibleObject accessibleObject = item.AccessibilityObject; + + Assert.Equal("Item, Value 1, Value 2", accessibleObject.Name); + Assert.Empty(accessibleObject.TestAccessor.Dynamic._listViewSubItemAccessibleObjects); + Assert.False(control.IsHandleCreated); + } + + [WinFormsFact] + public void ListViewItemDetailsAccessibleObject_Name_FullRowSelectWithoutColumns_ReturnsItemText() + { + using ListView control = new() + { + FullRowSelect = true, + View = View.Details + }; + + ListViewItem item = new("Item"); + control.Items.Add(item); + + Assert.Equal("Item", item.AccessibilityObject.Name); + Assert.False(control.IsHandleCreated); + } + [WinFormsFact] public void ListViewItemDetailsAccessibleObject_FragmentNavigate_FirstChild_ReturnsExpected() {