如何仅当WPF ComboBoxItem是所选项并且满足条件时才对其设置属性

本文关键字:条件 属性 设置 满足 ComboBoxItem WPF 何仅当 选项 | 更新日期: 2023-09-27 18:19:27

只有当组合框项目是所选项目并且其基础ID与ItemSource中的最后一个ID匹配时,我才难以使组合框项目显示为红色字体。到目前为止,我得到的是,只有当它是所选项目时,它才会变成红色,但我如何检查底层属性"ID"是否与包含它的ObservableCollection中的最后一个项目匹配,即只有当SelectedItem的ID==Collection[Length-1].ID时?

<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
            ItemsSource="{Binding BillingCycles}" SelectedItem="{Binding SelectedBillingCycle}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding BillingCycleDescription}" >
                <TextBlock.Foreground>
                    <MultiBinding Converter="{StaticResource IsCurrentCycleColorConverter}">
                        <Binding Path="ItemsSource" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                        <Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                        <Binding RelativeSource="{RelativeSource AncestorType={x:Type ComboBoxItem}}"/>
                    </MultiBinding>
                </TextBlock.Foreground>
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

因此,如果SelectedBillingCycle.ID!=BillingCycles[BillingCycle.Length-1].ID,文本应该显示为红色。我不知道我该如何引用BillingCycles[BillingCycles.Length-1]将其与.进行比较

///编辑:

更改了XAML,这越来越近了,但更改了所有组合框项,而不仅仅是selectedItem。我想我需要使用某种模板选择器,或者完全重新思考XAML。

如何仅当WPF ComboBoxItem是所选项并且满足条件时才对其设置属性

试试这个:假设我有一个UserType类

public class UserType
{
    public string Name { get; set; }
    public string Description { get; set; }
}

并且我已经将UserType的ObservableCollection绑定到项目ComboBox 的源

public ObservableCollection<UserType> UserTypes { get; set; }

xaml

    <Window.Resources>
    <local:ComboBoxForegroundConverter x:Key="ComboConv"/>
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="Foreground">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource ComboConv}">
                    <Binding Path="ItemsSource" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                    <Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                    <Binding/>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<StackPanel>
    <ComboBox ItemsSource="{Binding UserTypes}" DisplayMemberPath="Name"/>
</StackPanel>

多值转换器

    public class ComboBoxForegroundConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values != null && values.Count() == 3)
        {
            var itemsSource = values[0] as ObservableCollection<UserType>;//This is the Type of you Collection binded to ItemsSource
            if (itemsSource != null && itemsSource.Any() && itemsSource.Last() == values[1] && values[2]==values[1])
                return new SolidColorBrush(Colors.Red);
        }
        return new SolidColorBrush(Colors.Black);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在您的情况下,DisplayMember路径将为BillingCycleDescription。

我最终不得不使用DataTemplateSelector类来区分SelectedItem和其他comboxItems:

public class ComboBoxItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate SelectedTemplate { get; set; }
    public DataTemplate DropDownTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ComboBoxItem comboBoxItem = container.GetVisualParent<ComboBoxItem>();
        if (comboBoxItem == null)
        {
            return SelectedTemplate;
        }
        return DropDownTemplate;
    }
}

这个扩展类:

public static T GetVisualParent<T>(this DependencyObject child) where T : Visual
    {
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }

这是XAML:

<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
                  ItemsSource="{Binding BillingCycles}" SelectedItem="{Binding SelectedBillingCycle}">
            <ComboBox.ItemTemplateSelector>
                <b:ComboBoxItemTemplateSelector>
                    <b:ComboBoxItemTemplateSelector.SelectedTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding BillingCycleDescription}">
                                <TextBlock.Foreground>
                                    <MultiBinding Converter="{StaticResource IsCurrentCycleColorConverter}">
                                        <Binding Path="ItemsSource" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                                        <Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}"/>
                                    </MultiBinding>
                                </TextBlock.Foreground>
                            </TextBlock>
                        </DataTemplate>
                    </b:ComboBoxItemTemplateSelector.SelectedTemplate>
                    <b:ComboBoxItemTemplateSelector.DropDownTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding BillingCycleDescription}" />
                        </DataTemplate>
                    </b:ComboBoxItemTemplateSelector.DropDownTemplate>
                </b:ComboBoxItemTemplateSelector>
            </ComboBox.ItemTemplateSelector>
        </ComboBox>

使用这个转换器,我在Ethicalologs:的帮助下找到了这个转换器

public class IsCurrentCycleColorConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        SolidColorBrush color = new SolidColorBrush(Colors.Black);
        if (values != null && values.Count() == 2)
        {
            var itemsSource = values[0] as ObservableCollection<BillingCycle>;//This is the Type of you Collection binded to ItemsSource
            if (!(itemsSource != null && itemsSource.Any() && itemsSource.First() == (BillingCycle)values[1]))
            {
                color = new SolidColorBrush(Colors.DarkRed);
            }
        }
        return color;
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}