반응형
WPF 에서 TabControl을 사용하다보면 Tab을 추가 및 삭제 처리를 해야하는 경우가 많다.
Main Content에 쓰이는 TabControl에는 대부분 Tab Header에 닫기 버튼이 존재 하는경우가 다수 있다.
기본 TabControl에는 존재 하지 않으니 MVVM 패턴을 이용하여 이를 구현하는 방법에 대해 알아보도록 하자.
일단 기본적으로 ItemsSource에 들어갈 기본 객체를 선언해보자.
public interface ITab
{
string Header { get; set; }
ICommand CloseCommand { get; }
event EventHandler CloseEvent;
object DataContext { get; set; }
}
public class Tab : ITab
{
public Tab()
{
CloseCommand = new ActionCommand(m => CloseEvent?.Invoke(this, EventArgs.Empty));
}
public string Header { get; set; }
public ICommand CloseCommand { get; }
public object DataContext { get; set; }
public event EventHandler CloseEvent;
}
CloseCommand는 닫기 버튼에 바인딩할 인터페이스를 선언해 준것이며, 이것에 CloseEvent라는 Eventhandler를 Invoke처리하도록 해두었다.
<Window x:Class="DesignUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:DesignUI"
xmlns:vm="clr-namespace:DesignUI.ViewModel"
xmlns:view="clr-namespace:DesignUI.View"
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Grid>
<TabControl ItemsSource="{Binding Tabs}">
<!--표시할 화면과 DataContext 연결-->
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:Tab}">
<view:SampleView DataContext="{Binding DataContext}"/>
</DataTemplate>
</TabControl.Resources>
<!--Header 부분과 Close Button Template 구성-->
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:Tab}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Header}"/>
<Button Content="X" Command="{Binding CloseCommand}"/>
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DesignUI.ViewModel
{
class MainViewModel
{
private ObservableCollection<ITab> tabs { get; }
public ObservableCollection<ITab> Tabs { get; }
public MainViewModel()
{
tabs = new ObservableCollection<ITab>();
tabs.CollectionChanged += Tabs_CollectionChanged;
tabs.Add(new Tab() { DataContext = "First Tab", Header = "Tab1" });
tabs.Add(new Tab() { DataContext = "Second Tab", Header = "Tab2" });
tabs.Add(new Tab() { DataContext = "Third Tab", Header = "Tab3" });
Tabs = tabs;
}
private void Tabs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// 추가 삭제 시 Event를 연결 및 해제
switch (e.Action)
{
// 추가 할 경우
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
var newtab = e.NewItems[0] as ITab;
newtab.CloseEvent += OnTabCloseEvent;
break;
// 삭제 할 경우
case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
var deltab = e.OldItems[0] as ITab;
deltab.CloseEvent -= OnTabCloseEvent;
break;
}
}
private void OnTabCloseEvent(object sender, EventArgs e)
{
Tabs.Remove((ITab)sender);
}
}
}
<UserControl x:Class="DesignUI.View.SampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DesignUI.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock Text="{Binding }"/>
</Grid>
</UserControl>
닫기 버튼을 누르면 잘되는것을 확인할 수 있다.
디자인만 잘해놓으면 기능은 위로 구현 가능하니 다들 화이팅
반응형
'프로그래밍 > WPF' 카테고리의 다른 글
[WPF] ComboBox 선택에 따라 컨트롤 바꾸기 - Control Switching by ComboBox (0) | 2022.09.26 |
---|---|
[WPF] 오류 해결: 리소스를 찾을 수 없습니다. 리소스 이름은 대/소문자를 구분합니다. (0) | 2022.09.23 |
[WPF] ListView & ItemsControl 홀수/짝수 번째 배경색 변경하기 (1) | 2022.09.20 |
[WPF] ListView ListViewItme 사이의 Margin Padding 제거 (0) | 2022.09.16 |
[WPF] Label & Button 에 언더바 (Under bar) 쓰기 - RecognizesAccessKey (0) | 2022.09.16 |