ユーザー コントロールは、コレクションのアイテムではなくコレクション自体にバインドされているため (コンバーターが内部でこの作業を行います)、ユーザー コントロールのバインドを更新する場合は、コレクション全体で PropertyChanged を呼び出す必要があります。
編集:完全なソリューション
ビューモデル:
public class MainWindowViewModel : INotifyPropertyChanged
{
public ObservableCollection<Tag> Tags { get; private set; }
public MainWindowViewModel()
{
Tags = new ObservableCollection<Tag>();
Tags.Add(new Tag("Tag1", 111));
Tags.Add(new Tag("Tag2", 222));
Tags.Add(new Tag("Tag3", 333));
Tags.Add(new Tag("Tag4", 444));
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public void ChangeRandomTag()
{
var rand = new Random();
var tag = Tags[rand.Next(0, Tags.Count - 1)];
tag.Value = rand.Next(0, 1000);
OnPropertyChanged("Tags");
}
}
XAML を表示:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<wpfApplication1:MyConverter x:Key="MyConverter" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Tags}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="1"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="2">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Value}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Column="1" Orientation="Vertical">
<Button x:Name="buttonChangeRandomTag"
Click="ButtonChangeRandomTag_OnClick"
Content="Change Random Tag Value" />
<TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag1}" />
<TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag2}" />
<TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag3}" />
<TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag4}" />
</StackPanel>
</Grid>
コードビハインドを表示:
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new MainWindowViewModel();
InitializeComponent();
}
private void ButtonChangeRandomTag_OnClick(object sender, RoutedEventArgs e)
{
(DataContext as MainWindowViewModel).ChangeRandomTag();
}
}
コンバータ:
[ValueConversion(typeof(ObservableCollection<Tag>), typeof(int))]
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var collection = value as ObservableCollection<Tag>;
var key = parameter as string;
if (collection == null || parameter == null)
return 0;
var result = collection.FirstOrDefault(item => item.Name.Equals(key));
if (result == null)
return 0;
return result.Value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
タグクラス:
public class Tag : INotifyPropertyChanged
{
private string name;
private int value;
public string Name
{
get { return name; }
set
{
if (value == name) return;
name = value;
OnPropertyChanged("Name");
}
}
public int Value
{
get { return value; }
set
{
if (value == this.value) return;
this.value = value;
OnPropertyChanged("Value");
}
}
public Tag(string name, int value)
{
Value = value;
Name = name;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}