ObservableCollection は要素の追加・削除に関する変更は監視しますが、コレクション内の要素のプロパティが変更された場合には自動で再描画はされません。要素のプロパティが変更された場合にも自動的に再描画されるようにするには、コレクション内の各要素に**INotifyPropertyChanged インターフェイス**を実装する必要があります。
INotifyPropertyChanged を使った再描画の実現方法
UserControlのデータモデルクラスにINotifyPropertyChangedを実装- プロパティが変更されると通知が発生し、UIが再描画
以下に例を示します。
1. データモデルクラスの作成
まず、UserControl の中身に表示されるデータを持つモデルクラス UserControlData を作成し、INotifyPropertyChanged を実装します。
using System.ComponentModel;
namespace YourNamespace
{
public class UserControlData : INotifyPropertyChanged
{
private string _displayText;
public string DisplayText
{
get => _displayText;
set
{
if (_displayText != value)
{
_displayText = value;
OnPropertyChanged(nameof(DisplayText));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2. UserControl のバインディング設定
次に、UserControl の TextBlock などの表示要素を、UserControlData の DisplayText プロパティにバインドします。
SampleUserControl.xaml
<UserControl x:Class="YourNamespace.SampleUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Text="{Binding DisplayText}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
</Grid>
</UserControl>
SampleUserControl.xaml.cs
SampleUserControl のコードビハインドで、UserControlData をデータコンテキストとして設定します。
using System.Windows.Controls;
namespace YourNamespace
{
public partial class SampleUserControl : UserControl
{
public SampleUserControl(UserControlData data)
{
InitializeComponent();
DataContext = data;
}
}
}
3. MainWindow での使用
MainWindow の OnAddUserControlClick メソッドを修正し、UserControlData のインスタンスを使って SampleUserControl を作成し、UserControlCollection に追加します。
using System;
using System.Collections.ObjectModel;
using System.Windows;
namespace YourNamespace
{
public partial class MainWindow : Window
{
private readonly ObservableCollection<UserControl> UserControlCollection;
private int currentIndex = 0;
public MainWindow()
{
InitializeComponent();
UserControlCollection = new ObservableCollection<UserControl>();
}
private void OnAddUserControlClick(object sender, RoutedEventArgs e)
{
if (currentIndex < userControlTypes.Length)
{
// 新しい UserControlData を作成
var data = new UserControlData { DisplayText = $"Control {currentIndex + 1}" };
var control = new SampleUserControl(data);
UserControlCollection.Add(control);
currentIndex++;
}
}
// 任意のメソッドで UserControlData のプロパティを更新
private void UpdateUserControlText(int index, string newText)
{
if (index >= 0 && index < UserControlCollection.Count)
{
// UserControl を取り出し、DataContext の DisplayText プロパティを更新
var control = UserControlCollection[index] as SampleUserControl;
var data = control?.DataContext as UserControlData;
if (data != null)
{
data.DisplayText = newText;
}
}
}
}
}
説明
INotifyPropertyChangedの実装UserControlDataクラスはINotifyPropertyChangedを実装しており、DisplayTextプロパティの値が変更されるとPropertyChangedイベントが発生します。これにより、バインドされている UI 要素が自動的に更新されます。UpdateUserControlTextメソッドでのデータ更新UpdateUserControlTextメソッドを呼び出し、特定のUserControlDataのDisplayTextプロパティを更新することで、UI が再描画されます。バインディングの動作
SampleUserControlのTextBlockはDisplayTextプロパティにバインドされているため、DisplayTextの値が変更されると自動的に再描画が行われ、UI に反映されます。


コメント