WPF, XAML

(WPF기초강좌)ListBox와 Linq 쿼리를 이용한 간단한 데이터바인딩, 새창 띄우기, 이벤트 및 델리게이트를 통한 메인윈…

FSP 0 259 02.23 11:46

ListBoxLinq 쿼리를 이용한 간단한 데이터바인딩, 새창 띄우기, 이벤트 및 델리게이트를 통한 메인윈도우의 ListBox Refresh 적용 실습

n  직무타입(내근:Inner, 외근:OutSide)과 직무목록을 보여주는 두개의 ListBox 컨트롤을 사용해서 직무타입을 선택하면 Linq를 통해 해당 직무타입의 직무를 쿼리해서 하단의 ListBox에 보여주는 예제이다.

 

n  직무추가버튼을 클릭하면 새창이 뜨고 직무를 입력 후 저장 버튼을 클릭하면 직무입력 화면이 사라지고 메인 윈도우 상단의 ListBox가 새창에서 입력한 직무타입으로 선택되면서 하단의  ListBox는 해당 직무타입의 직무목록으로 자동으로 Refresh 된다.



 

 

n  WPF 프로젝트를 생성하자. (본 예제에서는 프로젝트명을 WpfApp1”로 설정했다.)

n  [Duty.cs]

using System.ComponentModel;

using System.Collections.ObjectModel;

 

namespace WpfApp1

{

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

        }

    }

}

 

n  [MainWindow.xaml]

<Window x:Class="WpfApp1.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:local="clr-namespace:WpfApp1"

        Title="MainWindow"

        SizeToContent="WidthAndHeight" Height="600">

    <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}"/>

                    <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="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"

                 HorizontalContentAlignment="Stretch"

                 ItemsSource="{Binding}"

                 ItemTemplate="{StaticResource MyTemplate}"

                 SelectionChanged="OnSelected2"/>

    </StackPanel>

</Window>

 

n  [MainWindow.xaml.cs]

using System.Linq;

using System.Windows;

using System.Windows.Controls;

 

namespace WpfApp1

{

    public partial class MainWindow : Window

    {

        internal static Duties duties = new Duties();

 

        public MainWindow()

        {

            InitializeComponent();

        }

 

        // 상단 ListBox의 항목(직무타입)을 선택했을 때

        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;

            }

        }

 

        //하단 ListBox의 항목(직무)를 선택했을 때

        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, "선택한 직무" );

        }

 

        // 직무추가 버튼을 클릭 했을 때 새창을 띄움.

        private void OpenNewWindow(object sender, RoutedEventArgs e)

        {

            SubWindow subWindow = new SubWindow();

 

            RefreshListEvent += new RefreshList(RefreshListBox); // event initialization

            subWindow.UpdateActor = RefreshListEvent; // assigning event to the Delegate

            subWindow.Show();

        }

 

        // 아래쪽 ListBox Refresh 하기위한 델리게이트 및 이벤트

        public delegate void RefreshList(DutyType dutyType);

        public event RefreshList RefreshListEvent;

 

        // RefreshListEvent 이벤트가 발생했 을 때 호출되는 메소드

        private void RefreshListBox(DutyType dutyType)

        {

            // 내근은 SelectedIndex 0, 외근은 SelectedIndex 1로 설정하여

            // 상단 ListBox의 선택값을 변경 시킨다.

            // 상단 ListBox의 값이 바뀜에 따라 OnSelected 이벤트 핸들러가 호출되어

            // 자동으로 아래쪽 ListBox의 값은 변경된다.

            myListBox1.SelectedItem = null;

            myListBox1.SelectedIndex = (dutyType == DutyType.Inner)? 0 : 1;

 

           

        }

    }

}

 

n  [SubWindow.xaml]

<Window x:Class="WpfApp1.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:WpfApp1"

        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="100" HorizontalAlignment="Center"

                Click="Button_Click" Height="22">저장</Button>

    </Grid>

 

</Window>

 

n  [SubWindow.xaml.cs]

using System;

using System.Windows;

 

namespace WpfApp1

{

    public partial class SubWindow : Window

    {

        // 메인 윈도우의 하단 ListBox Refresh하기 위한 델리게이트

        // 메인 윈도우에서 직무추가 버튼을 클릭할 때 이벤트를 할당해 준다.

        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();

        }

    }

}

 

 

Comments