リストボックスとテキスト ボックスを含む基本的なコントロールがあり、リストボックスがオブジェクトのコレクションにバインドされ、基本的なデータ テンプレートがあるとします。
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Top">Book name</TextBlock>
<TextBox x:Name="bookNameTextBox" DockPanel.Dock="Top" />
<TextBlock DockPanel.Dock="Top">Authors</TextBlock>
<ListBox ItemsSource="{Binding Authors}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
public class Author : INotifyPropertyChanged
{
public string Name { get; set; }
public ObservableCollection<Book> Books { get; }
}
public class Book : INotifyPropertyChanged
{
public string Name { get; }
}
私がやりたいことは、その著者が提供された名前に一致する本を持っているかどうかに応じて、リストボックス内のアイテムの色を変えることです。
Colour = author.Books.Any(b => b.Name.StartsWith(bookNameTextBox.Text)) ? Red : Black;
私は当初、MultiBinding とコンバーターを使用してこれを行うことができると考えていましたが、本のコレクションにアイテムが追加/削除されたとき、または本の名前が変更されたときにバインディングを更新する方法を理解できませんでした。
ロジックに影響を与える可能性のあるさまざまな変更のすべてに応じて、色が正しく更新されるようにするにはどうすればよいでしょうか? 例えば
- 書籍名の変更
- コレクションの追加と削除中の本
- テキスト ボックスのテキストが
bookNameTextBox
変化する
私のMultiBindingはこのように見えました
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource MyConverter}">
<Binding Path="Books" />
<Binding Path="Text" ElementName="bookNameTextBox" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
そして、私のコンバーター(実装IMultiValueConverter
)は次のようになりました
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var text = (string)values.First(v => v is string);
var books = (IEnumerable<Book>)values.First(v => v is IEnumerable<Book>);
return books.Any(b => b.Name.StartsWith(text));
}
これは機能しましたが、書籍を変更したり、書籍を追加したりすると、バインディングが何らかの形で更新されるまで、リスト項目のテキストの色が更新されませんでした。