より良い解決策は、DataTemplate でビュー モデルを使用することだと思います。コードを設定したら、エラーの可能性はほとんどなく、何度も再利用できます。
ビューモデルは次のようになります
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<ItemViewModel> _items;
public ViewModel()
{
_items = new ObservableCollection<ItemViewModel>(new List<ItemViewModel>()
{
new ItemViewModel() { Label = "Item1", IsChecked = false },
new ItemViewModel() { Label = "Item2", IsChecked = true },
new ItemViewModel() { Label = "Item3", IsChecked = true },
new ItemViewModel() { Label = "Item4", IsChecked = false },
new ItemViewModel() { Label = "Item5", IsChecked = false },
});
}
public ObservableCollection<ItemViewModel> Items
{
get
{
return this._items;
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class ItemViewModel : INotifyPropertyChanged
{
private bool _isChecked = false;
private string _label = "Label";
public ICommand ButtonCommand { get; private set; }
public ItemViewModel()
{
this.ButtonCommand = new DelegateCommand(Com_ButtonCommand);
}
public void Com_ButtonCommand(object parameter)
{
this.Label = "New Label text";
}
public string Label
{
get
{
return this._label;
}
set
{
this._label = value;
this.OnPropertyChanged("Label");
}
}
public bool IsChecked
{
get
{
return this._isChecked;
}
set
{
this._isChecked = value;
this.OnPropertyChanged("IsChecked");
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
ここには 3 つのクラスがあり、そのうちの 1 つはヘルパーです。
ViewModel --> メインの ViewModel、ItemViewModel --> 各アイテムのモデル、DelegateCommand --> ボタンをビュー モデルにマップできます
xamlは次のようになります
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Silver">
<CheckBox IsChecked="{Binding IsChecked}" Content="CheckBox" VerticalAlignment="Center"/>
<Label Content="{Binding Label}" Padding="5,0" Width="260" VerticalAlignment="Center" Background="#F3D6D6D6" Margin="5,0"/>
<Button Command="{Binding ButtonCommand}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
「{Binding}」キーワードに注意してください。これは、各データ テンプレートを独自のビュー モデル (この場合は IsChecked および Label) のその名前を持つメンバーに「バインド」します。
ViewModel をロードするには、ユーザー コントロールのコード ビハインドに次の行を追加します (MVVM を使用すると、ユーザー コントロールのコード ビハインドに触れることはほとんどありません)。
this.DataContext = new ViewModel();
ビューモデルを初めて見るときは、大変な作業のように思えるかもしれませんが、ほとんどが再利用可能であり、このようなことを行うためのデファクト スタンダード (MVVM) です。開始するために必要なすべてのコードが含まれています。
次のクラスと DelegateCommand は、後で使用するために保持する必要があります。上記のスニペットには既に含まれています。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}