Другой подход с MultiBinding
: я передаю коллекцию в качестве параметра, ищу предыдущий элемент и проверяю, совпадают ли первые буквы.
Этот подход проще, если базовая коллекция имеет значение ObservableCollection<T>
и изменяется. Это также медленнее, так как отображение элемента требует поиска предыдущего элемента ( O (n) ), поэтому отображение n элементов равно O (n ^ 2) .
В Xaml:
<ListBox x:Name="lbExample" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource ResourceKey=first}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource prevComparerConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ListBox}}" Path="ItemsSource"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="{Binding Converter={StaticResource ResourceKey=rest}}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
И в коде:
public class PrevComparerConverter : IMultiValueConverter
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var item = (string)values[0];
var col = (ObservableCollection<string>)values[1];
var ind = col.IndexOf(item);
var res = true;
if (ind > 0 && item.Length > 0)
{
var prev = col[ind - 1];
if (prev.Length > 0 && char.ToLowerInvariant(prev[0]) == char.ToLowerInvariant(item[0]))
res = false;
}
return res;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}