WPF

DataGrid의 ComboBox바인딩 샘플

지오준 2021. 4. 10.
반응형

MVC를 기반으로 바인딩을 구성합니다.

 

1.Model클래스

- DataGrid용 모델클래스(CountryInformation)와 ComboBox(CommonType)용 Model클래스를 생성

- 생성한 클래스를 이용한 실제 바인딩이 이용할 메서드(GetCountryNameList, GetCountryInformationList)를 생성

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace Wpf_DataGrid_Sample.Model
{
    class DropDownListModel
    {
        /// <summary>
        /// 국가명리스트 Model
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<CommonType> GetCountryNameList()
        {
            ObservableCollection<CommonType> countryNames = new ObservableCollection<CommonType>();

            countryNames.Add(new CommonType { Name = "한국", Value = "KR" });
            countryNames.Add(new CommonType { Name = "미국", Value = "US" });
            countryNames.Add(new CommonType { Name = "영국", Value = "GB" });
            countryNames.Add(new CommonType { Name = "일본", Value = "JP" });
            countryNames.Add(new CommonType { Name = "중국", Value = "CN" });

            return countryNames;
        }

        /// <summary>
        /// 국가정보리스트 Model
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<CountryInformation> GetCountryInformationList()
        {
            ObservableCollection<CountryInformation> countryNames = new ObservableCollection<CountryInformation>();

            countryNames.Add(new CountryInformation { RowIndex = 1, CountryCode = "KR" });
            countryNames.Add(new CountryInformation { RowIndex = 2, CountryCode = "US" });
            countryNames.Add(new CountryInformation { RowIndex = 3, CountryCode = "GB" });
            countryNames.Add(new CountryInformation { RowIndex = 4, CountryCode = "JP" });
            countryNames.Add(new CountryInformation { RowIndex = 5, CountryCode = "CN" });

            return countryNames;
        }
    }

    /// <summary>
    /// DataGrid용 모델클래스
    /// </summary>
    public class CountryInformation
    {
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Property변경을 View에 전달
        /// </summary>
        /// <param name="propertyName"></param>
        private void RaisePropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        private void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            field = value;
            var h = this.PropertyChanged;
            if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); }
        }

        private int rowinde;

        /// <summary>
        /// 행번호
        /// </summary>
        public int RowIndex
        {
            get { return this.rowinde; }
            set { this.SetProperty(ref this.rowinde, value); }
        }

        private string countrycode;

        /// <summary>
        /// 국가코드
        /// </summary>
        public string CountryCode
        {
            get { return this.countrycode; }
            set { this.SetProperty(ref this.countrycode, value); }
        }
    }

    /// <summary>
    /// DropDownList의 데이터생성을 위한 CommonType 모델클래스
    /// </summary>
    public class CommonType : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Property변경을 View에 전달
        /// </summary>
        /// <param name="propertyName"></param>
        private void RaisePropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        private void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            field = value;
            var h = this.PropertyChanged;
            if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); }
        }

        private string value;
        
        /// <summary>
        /// 콤보막스 Value값(Value용)
        /// </summary>
        public string Value
        {
            get { return this.value; }
            set { this.SetProperty(ref this.value, value); }
        }

        private string name;

        /// <summary>
        /// 콤보막스 Name값(Display용)
        /// </summary>
        public string Name
        {
            get { return this.name; }
            set { this.SetProperty(ref this.name, value); }
        }
    }
}

2.Controller클래스

- DataGrid와ComboBox에 바인딩할 ViewItem생성

- ViewItem클래스의 Model(CountryNameList, CountryInformationList)에 Model클래스의 메서드(GetCountryNameList, GetCountryInformationList)를 불러올 메서드 생성(GetContryNameList, GetCountryInformationList)

- 중요포인트는 ViewItem클래스의 Model(CountryNameList, CountryInformationList)의 RaisePropertyChanged의 Property명과 실제 DataGrid와 ComboBox에 사용될 바인딩명이 동일해야 정상적으로 동작한다는 것입니다.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using Wpf_DataGrid_Sample.Model;

namespace Wpf_DataGrid_Sample.Controller
{
    class DropDownListContoller
    {
        //Model 클래스 선언
        DropDownListModel DropDownListModel = new DropDownListModel();

        /// <summary>
        /// DropDownlist 바인딩용 메서드
        /// </summary>
        /// <param name="dataContent"></param>
        public void GetContryNameList(Object dataContext)
        {
            DropDownListViewItem viewItem = (DropDownListViewItem)dataContext;

            viewItem.CountryNameList = DropDownListModel.GetCountryNameList();

            return;
        }

        /// <summary>
        /// DataGrid 바인딩용 메서드
        /// </summary>
        /// <param name="dataContent"></param>
        public void GetContryInformationList(Object dataContext)
        {
            DropDownListViewItem viewItem = (DropDownListViewItem)dataContext;

            viewItem.CountryInformationList = DropDownListModel.GetCountryInformationList();

            return;
        }
    }

    /// <summary>
    /// DropDownList화면에 사용할ViewItem 클래스 선언
    /// </summary>
    class DropDownListViewItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Property변경을 View에 전달
        /// </summary>
        /// <param name="propertyName"></param>
        private void RaisePropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 국가명리스트 Model전달 메서드
        /// </summary>
        private ObservableCollection<CommonType> countryNameList;

        public ObservableCollection<CommonType> CountryNameList
        {
            get { return countryNameList; }
            set
            {
                countryNameList = value;
                //ComboBox바인딩시 사용할 Name
                RaisePropertyChanged("CountryNameList");
            }
        }

        /// <summary>
        /// 국가정보리스트 Model전달 메서드
        /// </summary>
        private ObservableCollection<CountryInformation> countryInformationList;

        public ObservableCollection<CountryInformation> CountryInformationList
        {
            get { return countryInformationList; }
            set
            {
                countryInformationList = value;
                //DataGrid바인딩시 사용할 Name
                RaisePropertyChanged("CountryInformationList");
            }
        }
    }
}

3.View클래스

- 바인딩에 필요한 Controller를 선언합니다.

- DataContext는 Controller에 선언된ViewItem으로 초기화를 합니다.

- Contoller의 메소드와 DataContext를 매칭해서 바인딩 처리를 불러옵니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Wpf_DataGrid_Sample.Controller;

namespace Wpf_DataGrid_Sample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //Controller선언
        DropDownListContoller DropDownListContoller = new DropDownListContoller();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new DropDownListViewItem();
            ViewInit();
        }

        /// <summary>
        /// 화면초기화
        /// </summary>
        public void ViewInit()
        {
            //화면타이틀 설정
            this.Title = "국가리스트";

            //DataGrid내부에 있는 ComboBox에 국가리스트 바인딩
            DropDownListContoller.GetContryNameList(this.DataContext);

            //DataGrid데이터 바인딩
            DropDownListContoller.GetContryInformationList(this.DataContext);
        }
    }
}

4.디자인소스

- 중요포인트는 Controller에 선언된 Model의 Property명과 동일해야 정상적으로 바인딩이 동작한다는 것입니다.

<Window x:Class="Wpf_DataGrid_Sample.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:Wpf_DataGrid_Sample"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <Grid.Resources>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <Trigger Property="DataGridCell.IsSelected" Value="True">
                        <Setter Property="Background" Value="LightGray" />
                        <Setter Property="Foreground" Value="Black" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Grid.Resources>
                                              <!--DataContext에 매칭된 ViewItem에 선언된 모델의 Property명-->
        <DataGrid x:Name="dgDropDownBinding" ItemsSource="{Binding CountryInformationList}" Height="Auto" VerticalAlignment="Top" Width="auto" AutoGenerateColumns="False" CanUserAddRows="False" SelectionMode="Single">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <Label Name="lbRowCount" Content="Row Number" VerticalAlignment="Center" HorizontalAlignment="Left"></Label>
                    </DataGridTemplateColumn.Header>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock x:Name="nbRowCount" Text="{Binding RowIndex}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <Label Name="lbCountryName" Content="CountryName"></Label>
                    </DataGridTemplateColumn.Header>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>                                                                                                                    <!--DataContext에 매칭된 ViewItem에 선언된 모델의 Property명-->
                            <ComboBox Name="cbCountryName" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CountryNameList, Mode=OneWay}"
                                        IsSynchronizedWithCurrentItem="False"
                                        DisplayMemberPath="Name"
                                        SelectedValuePath="Value"
                                        SelectedValue="{Binding CountryCode}" Cursor="Hand" Height="25"></ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

5. 샘플화면

6. 참고사항

- 샘플소스를 참조해서 더좋은 코드를 만들어보세요.

Wpf_DataGrid_Sample.zip
0.06MB

반응형

댓글