diff --git a/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs b/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs
index 69a504e..8b92b16 100644
--- a/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs
+++ b/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs
@@ -112,6 +112,41 @@ namespace Spectre.Console
.ToList();
}
+ ///
+ /// Returns all parent items of the given .
+ ///
+ /// The item for which to find the parents.
+ /// The parent items, or an empty list, if the given item has no parents.
+ public IEnumerable GetParents(T item)
+ {
+ var promptItem = Tree.Find(item);
+ if (promptItem == null)
+ {
+ throw new ArgumentOutOfRangeException(nameof(item), "item not found in tree.");
+ }
+
+ var parents = new List>();
+ while (promptItem.Parent != null)
+ {
+ promptItem = promptItem.Parent;
+ parents.Add(promptItem);
+ }
+
+ return parents
+ .ReverseEnumerable()
+ .Select(x => x.Data);
+ }
+
+ ///
+ /// Returns the parent item of the given .
+ ///
+ /// The item for which to find the parent.
+ /// The parent item, or null if the given item has no parent.
+ public T? GetParent(T item)
+ {
+ return GetParents(item).LastOrDefault();
+ }
+
///
ListPromptInputResult IListPromptStrategy.HandleInput(ConsoleKeyInfo key, ListPromptState state)
{
diff --git a/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs b/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs
index b9bdcb5..a0ac81a 100644
--- a/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs
+++ b/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs
@@ -82,5 +82,75 @@ namespace Spectre.Console.Tests.Unit
// Then
choice.IsSelected.ShouldBeTrue();
}
+
+ [Fact]
+ public void Should_Get_The_Direct_Parent()
+ {
+ // Given
+ var prompt = new MultiSelectionPrompt();
+ prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
+
+ // When
+ var actual = prompt.GetParent("item");
+
+ // Then
+ actual.ShouldBe("level-2");
+ }
+
+ [Fact]
+ public void Should_Get_The_List_Of_All_Parents()
+ {
+ // Given
+ var prompt = new MultiSelectionPrompt();
+ prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
+
+ // When
+ var actual = prompt.GetParents("item");
+
+ // Then
+ actual.ShouldBe(new []{"root", "level-1", "level-2"});
+ }
+
+ [Fact]
+ public void Should_Get_An_Empty_List_Of_Parents_For_Root_Node()
+ {
+ // Given
+ var prompt = new MultiSelectionPrompt();
+ prompt.AddChoice("root");
+
+ // When
+ var actual = prompt.GetParents("root");
+
+ // Then
+ actual.ShouldBeEmpty();
+ }
+
+ [Fact]
+ public void Should_Get_Null_As_Direct_Parent_Of_Root_Node()
+ {
+ // Given
+ var prompt = new MultiSelectionPrompt();
+ prompt.AddChoice("root");
+
+ // When
+ var actual = prompt.GetParent("root");
+
+ // Then
+ actual.ShouldBeNull();
+ }
+
+ [Fact]
+ public void Should_Throw_When_Getting_Parents_Of_Non_Existing_Node()
+ {
+ // Given
+ var prompt = new MultiSelectionPrompt();
+ prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
+
+ // When
+ Action action = () => prompt.GetParents("non-existing");
+
+ // Then
+ action.ShouldThrow();
+ }
}
}