MVVM ListBox - 根据索引更改项目的背景

时间:2013-06-05 10:00:25

标签: c# wpf mvvm

我有一个ListBox,用于表示脚本语言中的文本行。我需要“单步”脚本,突出显示当前脚本行(比如绿色背景)。

modelview有一个“CurrentLine”属性,它是当前行的索引,所以我想我会在ItemContainerStyle上写一个触发器并使用转换器来确定列表框项的索引是否与CurrentLine。但是我很难将当前行值传递给转换器,因为它来自VM,我不能将非常量值作为参数传递给转换器。使用触发器的“值”也不能这样做。我怎样才能传递这些值?

1 个答案:

答案 0 :(得分:2)

CURRENTLINE作为参考类型曝光

修改ViewModel以将当前行保存为实际的LineViewModel(或者其他任何内容,具体取决于VM暴露行的方式),而不是选择的索引在我看来是更清晰的解决方案。

然后,您可以使用带有检查相等性的转换器的多重绑定来定义触发器:

<ListBox ItemsSource="{Binding Lines}" x:Name="List">
    <ListBox.Resources>
        <sample:EqualityConverter x:Key="Converter" />
    </ListBox.Resources>
    <ListBox.ItemContainerStyle>
        <Style TargetType="Control">
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource Converter}">
                            <Binding Path="DataContext.CurrentLine" ElementName="List" />
                            <Binding />
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Background" Value="Blue"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

转换器:

public class EqualityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values[0] == values[1];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

就是这样。

CURRENTLINE以STRING(价格类型)展示

如果您仍想使用整数索引,则可以对AlternationIndex进行uitilize。您将列表的AlternationCount设置为其项目数,这可确保每个项目都具有其唯一索引,然后绑定到ListBoxItem的附加属性ItemsSource.AlternationIndex。这样,您就不会混淆具有相同内容的行。

<ListBox ItemsSource="{Binding Resources}" x:Name="List" AlternationCount="{Binding Resources.Count}">
    <ListBox.Resources>
        <sample:EqualityConverter x:Key="Converter" />
    </ListBox.Resources>
    <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource Converter}">
                            <Binding Path="DataContext.CurrentItem" ElementName="List"/>
                                <Binding RelativeSource="{RelativeSource Self}" Path="(ItemsControl.AlternationIndex)"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Background" Value="Blue"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

您需要稍微修改转换器:

public class EqualityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return Equals(values[1], values[0] );
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}