DataGrid에 Column Base로 ItemsSource Binding하는 방법

기본적인 DataGrid 사용 방법은 다음과 같습니다.

XAML

<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Col1" Binding="{Binding Col1}"/>
        <DataGridTextColumn Header="Col2" Binding="{Binding Col2}"/>
    </DataGrid.Columns>
</DataGrid>

ViewModel

public class ViewModel : BindingObject
{
    private MyList mMyData = new MyList();
    public MyList MyData { get => mMyData; set => OnPropertyChanged(ref mMyData, value); }

    public ViewModel()
    {
        MyData.Add(new MyItem() { Col1 = "1", Col2 = "2" });
        MyData.Add(new MyItem() { Col1 = "3", Col2 = "4" });
        MyData.Add(new MyItem() { Col1 = "5", Col2 = "6" });
    }
}

public class MyList : ObservableCollection<MyItem> { }

public class MyItem
{
    public string Col1 { get; set; }
    public string Col2 { get; set; }
}

질문은 다음과 같습니다.

  1. XAML에서 Column base가 아닌 Row base의 Data Binding을 할 수 있는 방법이 있을까요?
  2. 위 방법이 없다면 DataTable을 이용하는 방법이 있을 것 같은데, ViewModel level에서 DataTable이 아닌 다른 방식으로 값을 입력했을 때 Column 단위로 데이터가 입력되도록 하는 방법이 있을까요?

여러가지 방법이 있을 수 있다고 생각하지만 이러한 경우 어떤 방법들을 쓰시는지 궁금합니다.

1 Like

제목은 Column Base 인데, 질문은 Row Base 이네요.

근데, 뭐를 원하시든, ~~ Base로 데이터 바인딩을 한다는게 무슨 말씀이신지도 명확하지 않군요. 사례를 들어 원하는 바에 대한 추가 설명이 필요할 듯 싶습니다.

그리고, 제 생각인데, 아마도 ObservableCollection 의 사용법을 숙지하지 않아서 생긴 질문 같습니다.

WPF 는 단일 객체와 바인딩할 수 있는 뷰 객체로 ContentControl (버튼, 라벨 등)이 있고, 컬렉션 객체에 바인딩할 수 있는 ItemsControl(DataGrid, ListView, CollectionView 등) 이 있습니다.

질문의 코드는 ItemsControl에 바인딩을 걸면서, ContentControl 에나 유효한 바인딩 방식을 사용하는 오류가 있습니다.

ItemsControl.ItemsSource 는 IEnumerable 이지만, 컬렉션의 변화(요소의 추가 삭제)
를 통지 받기 위해서는 INotifyCollectionChanged 를 요구합니다.

이러한 요구 조건을 만족하도록 설계해 놓은 게 ObservableCollection 입니다.
따라서, 질문의 코드는 아래와 같이 수정되어야 합니다.

   //  private MyList mMyData = new MyList();
   // public MyList MyData { get => mMyData; set => OnPropertyChanged(ref mMyData, value); }
   public MyList MyData { get; set; }

MyData 속성을 DataGrid.ItemsSource 에 바인딩하는 것이 ItemsControl에 바인딩을 거는 방식입니다.

여기에 좀 더 다이나믹하게 MyItem 의 변화도 통지하기를 원한다면, 아래와 같이 MyItem 이 INPC를 구현하거나 BindingObject를 파생하면 됩니다.

public class MyItem : INotifyPropertyChanged
{
    public string Col1 { // 통지 로직 }
    public string Col2 { // 통지 로직 }
}

이 경우, DataGrid 는 MyData 에서 요소가 삭제되거나, 추가되거나, 새로운 MyList 객체가 할당될 때 뿐만 아니라, 특정 요소의 속성이 변화될 때도 반영합니다.

MyData[0].Col1 = newCol1Vaule;

감사합니다. 명확하지않고 숙지하지않았다는 오해가 있었지만… 아무튼 의도와 다른 답변이고 기본적인 내용이지만 참고하겠습니다.