본문 바로가기
C#/WinUI3

[C#][WinUI3] 데이터 바인딩 시, 갱신되지 않는 문제 해결 (INotifyPropertyChanged)

by 부먹짱 2023. 6. 19.
반응형

(참고로 WPF에서도 거의 동일한 코드로 해결이 가능하다.)

 

ListView에 ObservableColletion<T>를 사용하여 데이터 바인딩을 구현하였다.

이 경우 추가/삭제는 잘 동작하지만 갱신이 되지않는 현상이 나타났다.

 

처음으로 시도한 방법은 수정하고 싶은 인덱스에 새로 데이터를 넣는 것이었다.

하지만 이 경우 ListView가 수정될 때마다 해당 row가 깜빡이고 selection이 해제되는 문제가 발생하였다.

 

    public class Data
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }

 

<ListView ItemsSource="{x:Bind trackView}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="40"/>
          <ColumnDefinition Width="40"/>
          <ColumnDefinition Width="60"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="{x:Bind Name}"/>
        <TextBlock Grid.Column="1" Text="{x:Bind Value}"/>
      </Grid>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

 

    public sealed partial class ExPage : Page
    {
    	private ObservableCollection<Data> DataCollection = new ObservableCollection<Data>();
        
        public ExPage
        {
            this.InitializeComponent();
            this.DataContext = this;
        }
        
        // 이름만 바꾸고 싶은 경우
        internal void Update(Int index)
        {
            Data data = new Data();
            data.Name = "New Name";
            data.Value = this.DataCollection[index].Value;
            this.DataCollection[index] = data;
        }
    }

 

서치 해보니  INotifyPropertyChanged 사용하여 데이터 변경을 즉시 반영하는 방법이 있었다.

 

 

반응형

 

INotifyPropertyChanged

1. Data 클래스에 INotifyPropertyChanged 인터페이스를 상속한다.

2. NotifyPropertyChanged() 함수를 생성한다.

3. 변수의 Set 함수에서 변수를 설정하면서 NotifyPropertyChanged() 함수를 호출한다.

 

public class Data : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged; // 상속 시, 자동 생성

    private void NotifyPropertyChanged(string prop) // 직접 작성
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }

    private string _Name;
    private string _Value;
    
    public string Name
    {
        get
        {
            return this._Name;
        }
        set
        {
            this._Name = value;
            NotifyPropertyChanged("Name"); // 인자 - 변수명과 동일한지 체크
        }
    }
    
    public string Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            this._Value = value;
            NotifyPropertyChanged("Value");
        }
    }
}

 

4. DataTemplated의 DataType을 지정한다.

5. 데이터를 바인딩할 때, Mode를 TwoWay로, UpdateSourceTrigger를 Data 클래스에 자동으로 생성되었던 PropertyChanged로 설정한다. 

 

<ListView ItemsSource="{x:Bind Data}">
  <ListView.ItemTemplate>
    <!-- DataType 설정 -->
    <DataTemplate x:DataType="local:Data">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="40"/>
          <ColumnDefinition Width="40"/>
          <ColumnDefinition Width="60"/>
        </Grid.ColumnDefinitions>
        <!--Mode, UpdateSourceTrigger 설정-->
        <TextBlock Text="{x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBlock Grid.Column="1" Text="{x:Bind Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
      </Grid>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

 

이렇게 해주면 Data의 원하는 속성만 변경하여도 갱신이 잘된다.

 

    public sealed partial class ExPage : Page
    {
    	private ObservableCollection<Data> DataCollection = new ObservableCollection<Data>();
        
        public ExPage
        {
            this.InitializeComponent();
            this.DataContext = this;
        }
        
        internal void Update(Int index, Data data)
        {
            this.DataCollection[index].Name = "New Name";
        }
    }

 

 

 

반응형

'C# > WinUI3' 카테고리의 다른 글

[C#][WinUI3] Window 크기 고정 및 기타 윈도우 설정 방법  (2) 2023.05.19

댓글