简体   繁体   English

所选项目更改时更改Tabitem样式

[英]Change tabitem style when selected item changes

I have a TabControl and a style for each of my TabItem (with a StyleSelector ). 我有一个TabControl和每个TabItem的样式(带有StyleSelector )。 I want each TabItem to change its style when the selected item changes. 我希望每个TabItem在所选项目更改时更改其样式。

So I create a TabItemCustom with a property IsItemAfterSelected : 所以,我创建了一个TabItemCustom与属性IsItemAfterSelected

public class TabItemCustom: TabItem
{
    public static readonly DependencyProperty IsItemAfterSelectedProperty =
    DependencyProperty.Register("IsItemAfterSelected",
        typeof(bool),
        typeof(TabItemCustom),
        new PropertyMetadata(false));
    public bool IsItemAfterSelected
    {
        get { return (bool)GetValue(IsItemAfterSelectedProperty ); }
        set { SetValue(IsItemAfterSelectedProperty , value); }
    }
}

This property has to contain True if one of the next items is selected. 如果选择了以下一项,则此属性必须包含True

I can know when the SelectedIndex changes with this DataTrigger : 我可以知道什么时候SelectedIndex这个变化DataTrigger

<sys:Boolean x:Key="StyleValueTrue">True</sys:Boolean>
<DataTrigger Binding="{Binding Path=SelectedIndex, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Mode=TwoWay, Converter={StaticResource ConverterTabItemAriane}}" Value="{StaticResource StyleValueTrue}">
    <Setter Property="IsItemAfterSelected" Value="{Binding Converter={StaticResource ConverterTabItemAriane}, RelativeSource={RelativeSource Self}}"/>
 </DataTrigger>

I use the same converter to detect if is the SelectedIndex (if integer always return True ) and to set my value: 我使用相同的转换器来检测是否为SelectedIndex (如果integer始终返回True )并设置我的值:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    if (value is DependencyObject)
    {
        DependencyObject container = (DependencyObject)value;
        var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
        var itemIndex = itemsControl.ItemContainerGenerator.IndexFromContainer(container);
        if (itemsControl is TabControl)
        {
            TabControl tabcontrol = (TabControl)itemsControl;
            if (tabcontrol.SelectedIndex >= itemIndex) return true;
            else return false;
        }
    }
    else if (value is int) return true;// selected index has changed
        return false;
    }

I've checked with breakpoints: when I change the selected item it goes in the converter and returns True . 我已经检查了断点:当我更改所选项目时,它将进入转换器并返回True But my Property is set only once on the loading of the TabControl . 但是我的Property在TabControl加载时仅设置了一次。 The Trigger always return the same value why the property is set once? Trigger总是返回相同的值,为什么属性设置一次?

When I'll be able to set this property my goal is to add a DataTrigger like this: 当我能够设置此属性时,我的目标是添加一个DataTrigger如下所示:

<DataTrigger Property="IsItemAfterSelected" Value="True">
    <Setter Property="Background" Value="Red" />
</DataTrigger>

I don't know if my approach is the easiest but I didn't found a better solution (I've tried removing StyleValueTrue and put True instead but same result). 我不知道我的方法是否最简单,但是我没有找到更好的解决方案(我尝试删除StyleValueTrue并放入True但结果相同)。

Any thoughts to solve this? 有什么想法可以解决这个问题?

If you want to do it with Binding s: 如果要使用Binding来执行此操作:

XAML: XAML:

<Style TargetType="{x:Type local:TabItemCustom}">
    <Setter Property="IsItemAfterSelected">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource ConverterTabItemAriane}">
                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TabControl}}"/>
                <Binding RelativeSource="{RelativeSource Self}"/>
                <Binding Path="SelectedIndex" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TabControl}}"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsItemAfterSelected" Value="True">
            <Setter Property="Background" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>

Converter: 转换器:

public class ConverterTabItemAriane : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        TabControl tabControl = values[0] as TabControl;
        TabItem tabItem = values[1] as TabItem;
        if (tabControl != null && tabItem != null && values[2] is int)
        {
            var selectedIndex = (int)values[2];
            var itemIndex = tabControl.ItemContainerGenerator.IndexFromContainer(tabItem);
            return selectedIndex >= itemIndex;
        }
        return false;
    }

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

If you want to do it inside your TabControl : 如果要在TabControl内执行此操作:

XAML: XAML:

<Style TargetType="{x:Type local:TabItemCustom}">
    <Style.Triggers>
        <Trigger Property="IsItemAfterSelected" Value="True">
            <Setter Property="Background" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>

TabControl: TabControl的:

public class TabControlCustom : TabControl
{
    protected override System.Windows.DependencyObject GetContainerForItemOverride()
    {
        return new TabItemCustom();
    }

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);

        int i = 0;
        foreach (var item in Items)
        {
            var tabItem = ItemContainerGenerator.ContainerFromItem(item) as TabItemCustom;
            if (tabItem != null)
            {
                tabItem.IsItemAfterSelected = SelectedIndex >= i;
            }
            i++;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM