7장. WPF ListBox와 LINQ쿼리를 이용한 간단한 데이터바인딩

7장. WPF ListBox와 LINQ쿼리를 이용한 간단한 데이터바인딩

참조

목적

  • WPF ListBox와 LINQ 쿼리를 이용하여 간단한 데이터바인딩 실습을 해봅니다.

Duty.cs

using System.Collections.ObjectModel;

namespace WPF07_Test
{
    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));
        }
    }

    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;
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="WPF07_Test.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:WPF07_Test"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="450">
    <Window.Resources>
        <local:Duties x:Key="duites"/>

        <DataTemplate x:Key="MyTemplate">
            <Border x: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="Duty Type : "/>
                    <TextBlock Grid.Row="1" Grid.Column="1"
                               Text="{Binding Path=DutyType}"/>
                    <Separator 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="Add_Click"
                Content="직무 추가"/>

        <TextBlock Margin="10 0 0 0" 
                   Text="직무 타입을 선택 하세요."/>

        <ListBox x:Name="myListBox1"
                 SelectionChanged="myListBox1_SelectionChanged"
                 SelectedIndex="0"
                 Margin="10 0 0 0">
            <ListBoxItem>Inner</ListBoxItem>
            <ListBoxItem>OutSide</ListBoxItem>
        </ListBox>

        <TextBlock Margin="10 10 0 -10" 
                   Text="직무"/>

        <ListBox x:Name="myListBox2"
                 Width="400" Margin="10"
                 HorizontalContentAlignment="Stretch"
                 ItemsSource="{Binding}"
                 ItemTemplate="{StaticResource MyTemplate}"
                 SelectionChanged="myListBox2_SelectionChanged">

        </ListBox>

    </StackPanel>
</Window>

MainWindow.xaml.cs

using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace WPF07_Test
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        internal static Duties duties = new Duties();

        // ListBox를 Refresh 하기 위한 Delegate 및 이벤트
        public delegate void RefreshList(DutyType dutyType);
        public event RefreshList RefreshListEvent;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            SubWindow subWindow = new SubWindow();

            RefreshListEvent += new RefreshList(RefreshListBox);
            subWindow.UpdateActor = RefreshListEvent;
            subWindow.Show();
        }

        private void RefreshListBox(DutyType dutyType)
        {
            //내근은 SelectedIndex를 0, 외근은 SelectedIndex를 1로 설정하여
            //상단 ListBox의 선택값을 변경시킨다.
            //상단 ListBox의 값이 바뀜에 따라 OnSelected 이벤트 핸들러가 호출되어
            //자동으로 아래쪽 ListBox의 값은 변경된다.
            myListBox1.SelectedItem = null;
            myListBox1.SelectedIndex = (dutyType == DutyType.Inner) ? 0 : 1;
        }

        private void myListBox1_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            ListBox lb = sender as ListBox;
            ListBoxItem item = lb.SelectedItem as ListBoxItem;

            if(lb.SelectedItem != null)
            {
                string dutyType = item.Content.ToString();

                this.DataContext = from duty in duties
                                   where duty.DutyType.ToString() == dutyType
                                   select duty;
            }
        }

        private void myListBox2_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            var duty = (Duty)myListBox2.SelectedItem;

            // string value = duty == null ? "No selection" : duty.ToString();

            MessageBox.Show($"{duty.DutyName} :: {duty.DutyType}", "선택한 직무");
        }
    }
}

SubWindow.xaml

<Window x:Class="WPF07_Test.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:WPF07_Test"
        mc:Ignorable="d"
        Title="SubWindow" Height="300" Width="300">
    <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 FontFamily="20"
                   Grid.ColumnSpan="3"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Text="직무 등록"/>

        <TextBlock Grid.Row="1" Margin="10"
                   VerticalAlignment="Center"
                   Text="직무명"/>

        <TextBox x:Name="txtDutyName"
                 Grid.Row="1" Margin="10"
                 Grid.Column="1"
                 Grid.ColumnSpan="2"/>

        <TextBlock Grid.Row="2" Margin="10"
                   Text="직무타입"/>
        <RadioButton x:Name="rdoInner"
                     Grid.Row="2" Grid.Column="1"
                     Content="내근"
                     VerticalAlignment="Center"
                     HorizontalAlignment="Center"/>

        <RadioButton x:Name="rdoOutside"
                     Grid.Row="2" Grid.Column="2"
                     Content="외근"
                     VerticalAlignment="Center"
                     HorizontalAlignment="Center"/>

        <Button x:Name="btnSave"
                Content="저장"
                Grid.Column="1"
                Grid.Row="3"
                Width="100"
                HorizontalAlignment="Center"
                VerticalAlignment="Center" Height="22"
                Click="btnSave_Click"/>
    </Grid>
</Window>

SubWindow.xaml.cs

using System;
using System.Windows;

namespace WPF07_Test
{
    /// <summary>
    /// SubWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class SubWindow : Window
    {
        //메인 윈도우의 하단 ListBox를 Refresh 하기 위한 델리게이트
        //메인 윈도우에서 직무추가 버튼을 클릭할 때 이벤트를 할당해준다.
        public Delegate UpdateActor;

        public SubWindow()
        {
            InitializeComponent();
        }

        private void btnSave_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);
        }
    }
}

실행결과

1

728x90

이 글을 공유하기

댓글

Designed by JB FACTORY