๐ณ WPF TreeView์์ ContextMenu๋ก ๋ ธ๋ ์ถ๊ฐ ๋ฐ ์ญ์ ๊ตฌํํ๊ธฐ
TreeView๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋
ธ๋๋ฅผ ๋์ ์ผ๋ก ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ์ ์๋ค๋ฉด ๋์ฑ ์ ์ฐํ UI๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
์ด๋ฒ ๊ธ์์๋ MVVM ํจํด์ ์ ์งํ๋ฉด์ ContextMenu(์ฐํด๋ฆญ ๋ฉ๋ด)๋ฅผ ํ์ฉํ์ฌ ๋
ธ๋๋ฅผ ์ถ๊ฐ/์ญ์ ํ๋ ๋ฐฉ๋ฒ์ ์์๋ด
๋๋ค.
๋ชฉ์ฐจ
1. Category ๋ชจ๋ธ ํด๋์ค ๊ตฌ์ฑ
public class Category
{
public string Name { get; set; }
public ObservableCollection<Category> Children { get; set; } = new();
}
2. ViewModel์์ ๋ช ๋ น ์ ์
public class MainViewModel
{
public ObservableCollection<Category> Categories { get; set; }
public ICommand AddCommand { get; }
public ICommand RemoveCommand { get; }
public MainViewModel()
{
Categories = new ObservableCollection<Category>
{
new Category
{
Name = "ํ๋ก๊ทธ๋๋ฐ ์ธ์ด",
Children = new ObservableCollection<Category>
{
new Category { Name = "C#" },
new Category { Name = "Python" }
}
}
};
AddCommand = new RelayCommand(AddNode);
RemoveCommand = new RelayCommand(RemoveNode);
}
private void AddNode(object? parameter)
{
if (parameter is Category category)
{
category.Children.Add(new Category { Name = "์ ํ์ ํญ๋ชฉ" });
}
}
private void RemoveNode(object? parameter)
{
if (parameter is Category category)
{
foreach (var parent in Categories.SelectMany(GetAllCategories))
{
if (parent.Children.Contains(category))
{
parent.Children.Remove(category);
return;
}
}
}
}
private IEnumerable<Category> GetAllCategories(Category category)
{
yield return category;
foreach (var child in category.Children.SelectMany(GetAllCategories))
yield return child;
}
}
3. TreeView์ ContextMenu XAML ๊ตฌ์ฑ
<TreeView ItemsSource="{Binding Categories}" Margin="10">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<StackPanel.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="ํ์ ํญ๋ชฉ ์ถ๊ฐ"
Command="{Binding DataContext.AddCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
<MenuItem Header="์ด ํญ๋ชฉ ์ญ์ "
Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
์ ์ฝ๋์์ DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"
๋
๋ฉ๋ด๊ฐ ๋
ธ๋ ์์ฒด๋ฅผ ๋ฐ์ธ๋ฉํ ์ ์๋๋ก ์ค์ ํด์ค๋๋ค.
4. ๋ ธ๋ ์ถ๊ฐ/์ญ์ ๋์ ํ์ธ
- ๋ ธ๋๋ฅผ ์ฐํด๋ฆญํ๋ฉด ํ์ ํญ๋ชฉ ์ถ๊ฐ / ํญ๋ชฉ ์ญ์ ๋ฉ๋ด๊ฐ ํ์๋ฉ๋๋ค.
- ํ์ ํญ๋ชฉ ์ถ๊ฐ ์ ํด๋น ๋ ธ๋์ ์์์ผ๋ก ์๋ก์ด ํญ๋ชฉ์ด ์ถ๊ฐ๋ฉ๋๋ค.
- ์ญ์ ์ ์์ ์ปฌ๋ ์ ์์ ํด๋น ๋ ธ๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ๋ชจ๋ ๋ก์ง์ MVVM ๊ตฌ์กฐ ์์์ Command + ViewModel ์ฒ๋ฆฌ๋ก ๋์ํฉ๋๋ค.
5. ๋ง๋ฌด๋ฆฌ ๋ฐ ๋ค์ ํธ ์๊ณ
์ด๋ฒ ๊ธ์์๋ WPF TreeView์์ ์ฐํด๋ฆญ ๋ฉ๋ด(ContextMenu)๋ฅผ ํ์ฉํ์ฌ ๋ ธ๋๋ฅผ ๋์ ์ผ๋ก ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ๋ ๊ธฐ๋ฅ์ MVVM ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ต๋๋ค.
- ContextMenu์์๋ CommandParameter๋ฅผ ํตํด ๋ฐ์ธ๋ฉ์ด ๊ฐ๋ฅํ๋ค!
- ์ญ์ ์์๋ ์ฌ๊ท์ ์ผ๋ก ๋ถ๋ชจ๋ฅผ ์ฐพ์์ ์ ๊ฑฐ
- ๋ชจ๋ ์ฝ๋๊ฐ ViewModel์ ์๊ณ View๋ Command์๋ง ์ฐ๊ฒฐ!
๋ค์ ์๋ฆฌ์ฆ์์๋ TreeView ๋
ธ๋์ ๋๋๊ทธ ์ค ๋๋กญ ๊ธฐ๋ฅ(DnD)์ ๋ค๋ฃฐ ์์ ์
๋๋ค.
๋ ํ์ฑํ TreeView UI๋ฅผ ๋ง๋ค ์ค๋น๋์
จ๋์? ๐
'C#' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
WPF TreeView ์ฒดํฌ๋ฐ์ค ๋ ธ๋ ๊ตฌํ (0) | 2025.04.11 |
---|---|
WPF TreeView Drag & Drop ๊ตฌํ (0) | 2025.04.10 |
WPF TreeView์ MVVM Command ๋ฐ์ธ๋ฉ (0) | 2025.04.09 |
WPF TreeView์ HierarchicalDataTemplate ์์ ์ ๋ณต (0) | 2025.04.08 |
WPF DataTemplate๊ณผ ItemsControl ์์ ์ดํด (0) | 2025.04.07 |