WPF treeview item background over entire row

前端 未结 3 1399
终归单人心
终归单人心 2020-12-10 16:14

i am writing one app and i need to set background under entire row by items. I found some inspiration in here but i cannot get idea how to get Border background value in tem

相关标签:
3条回答
  • 2020-12-10 16:39

    Use snoop to understand the visual tree you are trying to modify. This way it will take 2-3 minutes to actually know what you need to modify. ( google )

    My bet is that you need to use something like this:

    <TreeView>
    <TreeView.ItemContainerStyle>
    <Style BasedOn="{StaticResource {x:Type TreeViewItem}}" TargetType="TreeViewItem">
                        <Setter Property="Background" Value="Purple" />
    </TreeView.ItemContainerStyle>
    </TreeView>
    

    you will also need to add triggers if you want background colo depending on items.

    0 讨论(0)
  • 2020-12-10 16:55

    Thanks for your solution! Here's is a preview what I've done so far:

    preview

    <TreeView Grid.Row="1"  Name="treeView" Margin="5">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                <Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                <!-- Style for the selected item -->
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TreeViewItem}">
                            <ControlTemplate.Resources>
                                <Conv:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
                            </ControlTemplate.Resources>
                            <StackPanel>
                                <Border 
                                    x:Name="Bd"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    Padding="{TemplateBinding Padding}">
                                    <Grid Margin="{Binding Converter={StaticResource lengthConverter}, RelativeSource={RelativeSource TemplatedParent}}">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="19" />
                                            <ColumnDefinition/>
                                        </Grid.ColumnDefinitions>
                                        <ToggleButton 
                                            Grid.Column="0" 
                                            x:Name="Expander"
                                            Style="{StaticResource ExpandCollapseToggleStyle}"
                                            IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                                            ClickMode="Press"/>
                                        <ContentPresenter x:Name="PART_Header" Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ContentSource="Header" />
                                    </Grid>
                                </Border>
                                <ItemsPresenter x:Name="ItemsHost" />
                            </StackPanel>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsExpanded" Value="false">
                                    <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
                                </Trigger>
                                <Trigger Property="HasItems" Value="false">
                                    <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="HasHeader" Value="false"/>
                                        <Condition Property="Width" Value="Auto"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="HasHeader" Value="false"/>
                                        <Condition Property="Height" Value="Auto"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
                                </MultiTrigger>
                                <Trigger Property="IsSelected" Value="true">
                                    <!--<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>-->
                                    <Setter TargetName="Bd" Property="Background" Value="#FFF7D280"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsSelected" Value="true"/>
                                        <Condition Property="IsSelectionActive" Value="false"/>
                                    </MultiTrigger.Conditions>
                                    <!--<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>-->
                                    <Setter TargetName="Bd" Property="Background" Value="#FFDADADA"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                                </MultiTrigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <!-- Selected and has focus -->
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="BorderBrush" Value="{StaticResource HT_Background_Orange}"/>
                    </Trigger>
                    <!-- Mouse over -->
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="#FFFDE8BA"/>
                        <!--<Setter Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                    <GradientStop Color="#FFFAFBFD" Offset="0"/>
                                    <GradientStop Color="#fadfa3" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>-->
                        <Setter Property="BorderBrush" Value="#f59246"/>
                    </Trigger>
                    <!-- Selected but does not have the focus -->
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="True"/>
                            <Condition Property="IsSelectionActive" Value="False"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="BorderBrush" Value="#f59246"/>
                    </MultiTrigger>
                </Style.Triggers>
                <Style.Resources>
                    <Style TargetType="Border">
                        <Setter Property="CornerRadius" Value="0"/>
                    </Style>
                </Style.Resources>
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:FileSystemObjectInfo}" ItemsSource="{Binding Path=Children}">
                <StackPanel Orientation="Horizontal">
                    <Image
                        Source="{Binding Path=ImageSource, UpdateSourceTrigger=PropertyChanged}" 
                        Margin="0,1,8,1"
                        Height="24"
                        Width="24"/>
                    <TextBlock
                        Text="{Binding Path=FileSystemInfo.Name}"
                        VerticalAlignment="Center"/>
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <TreeView.Resources>
    
            <!-- Brushes for the selected item -->
            <LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0">
                <GradientStop Color="#FFFDF2DA" Offset="0"/>
                <GradientStop Color="#FFF7D280" Offset="1"/>
            </LinearGradientBrush>
            <LinearGradientBrush x:Key="{x:Static SystemColors.ControlBrushKey}" EndPoint="0,1" StartPoint="0,0">
                <GradientStop Color="White" Offset="0"/>
                <GradientStop Color="#FFE2E2E2" Offset="1"/>
            </LinearGradientBrush>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
            <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
        </TreeView.Resources>
    </TreeView>
    
    public class LeftMarginMultiplierConverter : IValueConverter
    {
        public double Length { get; set; }
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            TreeViewItem item = value as TreeViewItem;
            if (item == null)
                return new Thickness(0);
    
            return new Thickness(Length * item.GetDepth(), 0, 0, 0);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new System.NotImplementedException();
        }
    }
    
    public static class TreeViewItemExtensions
    {
        public static int GetDepth(this TreeViewItem item)
        {
            TreeViewItem parent;
            while ((parent = GetParent(item)) != null)
            {
                return GetDepth(parent) + 1;
            }
            return 0;
        }
    
        private static TreeViewItem GetParent(TreeViewItem item)
        {
            DependencyObject parent = item != null ? VisualTreeHelper.GetParent(item) : null;
            while (parent != null && !(parent is TreeViewItem || parent is TreeView))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }
            return parent as TreeViewItem;
        }
    }
    
    <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid
                    Width="15"
                    Height="13"
                    Background="Transparent">
                        <Path 
                        x:Name="ExpandPath"
                        HorizontalAlignment="Left" 
                        VerticalAlignment="Center" 
                        Margin="1,1,1,1"
                        Fill="{StaticResource GlyphBrush}"
                        Data="M 4 0 L 8 4 L 4 8 Z"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    If you have any questions, let me know!

    Regards

    0 讨论(0)
  • 2020-12-10 16:55

    Completing Dominic Jonas's solution, using GetChildOfType method from How to get children of a WPF container by type?:

    public class LeftMarginMultiplierConverter : IValueConverter
        {
            public int Length { get; set; }
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                Thickness thickness = new Thickness(0, 0, 0, 0);
                if (value != null)
                {
                    TreeViewItem treeViewItem = (TreeViewItem)value;
                    ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(treeViewItem);
                    if (parent != null)
                    {
                        if (parent.GetType() == typeof(TreeView))
                        {
                            thickness = new Thickness(System.Convert.ToDouble(Length), 5, 5, 5);
                        }
                        else if (parent.GetType() == typeof(TreeViewItem))
                        {
                            Grid grid = (Grid) Helper.GetChildOfType<Grid>(parent);
                            if(grid != null)
                                thickness = new Thickness(System.Convert.ToDouble(grid.Margin.Left + Length), 5, 5, 5);
                        }
                    }
                }
                return thickness;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
        public static class Helper
        {
            public static T GetChildOfType<T>(this DependencyObject depObj) where T : DependencyObject
            {
                if (depObj == null) return null;
    
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    var child = VisualTreeHelper.GetChild(depObj, i);
    
                    var result = (child as T) ?? GetChildOfType<T>(child);
                    if (result != null) return result;
                }
                return null;
            }
        }
    

    And Highlight mouse over in only single row: How can I make WPF Trigger for IsMouseOver on TreeViewItem NOT affect all parents of the moused-over control?

    0 讨论(0)
提交回复
热议问题