8. 메인 윈도우의 ListBox Refresh 적용 실습
- ListBox와 LINQ 쿼리를 이용해 간단한 데이터바인딩, 새창 띄우기, 이벤트 및 델리게이트를 통한 메인 윈도우의 ListBox Refresh 적용 실습
- 직무타입(내근:Inner, 외근:OutSide)과 직무목록을 보여주는 두개의 ListBox 컨트롤을 사용해서 직무타입을 선택하면 Linq를 통해 해당 직무타입의 직무를 쿼리해서 하단의 ListBox에 보여주는 예제이다.
- “직무추가” 버튼을 클릭하면 새창이 뜨고 직무를 입력 후 저장 버튼을 클릭하면 직무입력 화면이 사라지고 메인 윈도우 상단의 ListBox가 새창에서 입력한 직무타입으로 선택되면서 하단의 ListBox는 해당 직무타입의 직무목록으로 자동으로 Refresh 된다.

실습
- 프로젝트 생성 -> 프로젝트 우클릭 -> 추가 -> 새항목 -> 코드 -> 클래스(클래스명: Duty.cs)
- Duty.cs
using System.Collections.ObjectModel;
namespace WpfApp2
{
public enum DutyType
{
Inner,
OutSide
}
public class Duty
{
private string _name;
private DutyType _dutyType;
public Duty() { }
public Duty(string name, DutyType dutyType)
{
_name = name;
_dutyType = dutyType;
}
public string DutyName
{
get { return _name; }
set
{
_name = value;
}
}
public DutyType DutyType
{
get { return _dutyType; }
set
{
_dutyType = value;
}
}
}
public class Duties : ObservableCollection<Duty>
{
public Duties()
{
Add(new Duty("SALES", DutyType.OutSide));
Add(new Duty("LOGISTICS", DutyType.OutSide));
Add(new Duty("IT",DutyType.Inner));
Add(new Duty("MARKETING", DutyType.Inner));
Add(new Duty("HR", DutyType.Inner));
Add(new Duty("PROPOTION",DutyType.OutSide));
}
}
}
- 프로젝트 우클릭 -> 새항목 -> WPF -> 창(WPF)(창 명 : SubWindow.xaml)
- xaml(SubWindow.xaml)
<Window x:Class="WpfApp2.SubWindow"
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:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="SubWindow" Height="230" Width="350">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontSize="20" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center">직무 등록</TextBlock>
<TextBlock Grid.Row="1" Margin="10" VerticalAlignment="Center">직무명</TextBlock>
<TextBox x:Name="txtDutyName" Grid.Row="1" Margin="10" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center"/>
<TextBlock Margin="10" Grid.Row="2" VerticalAlignment="Center">직무타입</TextBlock>
<RadioButton x:Name="rdoInner" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">내근</RadioButton>
<RadioButton x:Name="rdoOutside" Grid.Row="2" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center">외근</RadioButton>
<Button Grid.Column="1" Grid.Row="3" Width="80" HorizontalAlignment="Center" Click="Button_Click" Height="22">저장</Button>
</Grid>
</Window>
- xaml.cs(SubWindow.xaml.cs)
using System.Windows;
using System;
namespace WpfApp2
{
public partial class SubWindow : Window
{
public Delegate UpdateActor;
public SubWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (rdoInner.IsChecked == false && rdoOutside.IsChecked == false)
{
MessageBox.Show("내근 또는 외근을 선택하세요.", "항목선택");
return;
}
DutyType dutyType = (rdoInner.IsChecked == true) ? DutyType.Inner : DutyType.OutSide;
MainWindow.duties.Add(
new Duty(txtDutyName.Text,
dutyType
));
UpdateActor.DynamicInvoke(dutyType);
MessageBox.Show("저장OK!", "저장확인");
this.Close();
}
}
}
<Window x:Class="WpfApp2.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:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:Duties x:Key="duties"/>
<DataTemplate x:Key="MyTemplate">
<Border Name="border">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Duty Name: "/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=DutyName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="DutyType: "/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=DutyType}"/>
<TextBlock Grid.Row="2" Grid.ColumnSpan="2"/>
</Grid>
</Border>
</DataTemplate>
<LinearGradientBrush x:Key="GrayBlueGradientBrush" StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="DarkGray" Offset="0"/>
<GradientStop Color="#CCCCFF" Offset="0.5"/>
<GradientStop Color="DarkGray" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}"/>
<Setter Property="Width" Value="80"/>
<Setter Property="Margin" Value="10"/>
</Style>
</Window.Resources>
<StackPanel>
<Button x:Name="Add" Click="OpenNewWindow">직무 추가</Button>
<TextBlock Margin="10,0,0,0">직무타입을 선택 하세요.</TextBlock>
<ListBox Name="myListBox1" SelectionChanged="OnSelected" SelectedIndex="0" Margin="10,0,10,0">
<ListBoxItem>Inner</ListBoxItem>
<ListBoxItem>OutSide</ListBoxItem>
</ListBox>
<TextBlock Margin="10,10,0,-10">직무</TextBlock>
<ListBox Width="400" Margin="10" Name="myListBox2"
HorizontalAlignment="Stretch"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource MyTemplate}"
SelectionChanged="OnSelected2"/>
</StackPanel>
</Window>
- xaml.cs(MainWindow.xaml.cs)
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp2
{
public partial class MainWindow : Window
{
internal static Duties duties = new Duties();
public MainWindow()
{
InitializeComponent();
}
private void OpenNewWindow(object sender, RoutedEventArgs e)
{
SubWindow subWindow = new SubWindow();
RefreshListEvent += new RefreshList(RefreshListBox);
subWindow.UpdateActor = RefreshListEvent;
subWindow.Show();
}
public delegate void RefreshList(DutyType dutyType);
public event RefreshList RefreshListEvent;
private void RefreshListBox(DutyType dutyType)
{
myListBox1.SelectedItem = null;
myListBox1.SelectedIndex = (dutyType == DutyType.Inner) ? 0 : 1;
}
private void OnSelected(object sender, SelectionChangedEventArgs e)
{
if ((sender as ListBox).SelectedItem != null)
{
string dutyType = ((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString();
DataContext = from duty in duties
where duty.DutyType.ToString() == dutyType
select duty;
}
}
private void OnSelected2(object sender, SelectionChangedEventArgs e)
{
var duty = (Duty)myListBox2.SelectedItem;
string value = duty == null ? "No Selection" : duty.ToString();
MessageBox.Show(duty.DutyName + "::" + duty.DutyType, "선택한 직무");
}
}
}