假设我有一个带有列表框和文本框的基本控件,其中列表框绑定到对象集合并具有基本数据模板
<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));
}
但是,如果我随后修改了任何书籍,或者添加了任何书籍,那么在以某种方式刷新绑定之前,列表项的文本颜色不会更新。