【问题标题】:How to set a property on WPF ComboBoxItem only when it is the selected item and it satisfies condition?仅当 WPF ComboBoxItem 是选定项且满足条件时,如何在 WPF ComboBoxItem 上设置属性?
【发布时间】:2014-08-26 21:18:54
【问题描述】:

我无法使组合框项目仅在它是选定项目并且其基础 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,这越来越接近,但更改了所有组合框项,而不仅仅是选定项。我想我需要使用某种模板选择器或完全重新考虑 XAML。

【问题讨论】:

  • 看起来您必须使用ConverterID 转换为true(通过与BillingCycles[BillingCycle.Length-1].ID 进行比较(即Converter 用于Condition 中的绑定)。
  • 好的,但是我如何将 SelectedItem 的 ID AND 和 BillingCycles[BillingCycles.Length-1] 的 ID 指定给转换器?
  • 也许我需要两个模板?因为我只希望 SelectedItem 变成红色,而不是组合框中的其他项目?

标签: c# wpf xaml combobox itemtemplate


【解决方案1】:

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

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

并且我将 UserType 的 ObservableCollection 绑定到 ComboBox 的 itemsSource

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。

【讨论】:

  • 这非常接近,但它会将每个 ComboBoxItem 变成红色(或黑色)。我怎样才能只将 SelectedItem(当前选择的 ComboBoxItem)的颜色更改为红色?
  • 好的,我得到了,但是你想要在选择最后一个项目时combobox前景红色吗? span>
  • 如果满足条件,我只希望作为当前 SelectedItem 的 ComboBoxItem 将其前景更改为红色
  • 对于 var comboboxItem 我总是得到 null 而不是 comboboxitem 因为 values[2] 是 "{DependencyProperty.UnsetValue}"
  • 我已经测试过它工作正常。确保您没有在 Comboboxitem relativesource 的最后一个绑定中设置任何路径
【解决方案2】:

我最终不得不使用 DataTemplateSelector 类来区分 SelectedItem 和其他组合框项:

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>

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

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();
    }
}

【讨论】:

  • 很高兴你终于完成了。我在办公室所以无法回复。
  • 是的,对于小事来说,这似乎是一个荒谬的变化。无论如何,谢谢你的帮助!
猜你喜欢
  • 1970-01-01
  • 2021-12-03
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
相关资源
最近更新 更多