Как применить цвет подсветки TreeView, когда TreeViewItem содержит границу с DropShadowEffect? - PullRequest
0 голосов
/ 29 мая 2018

Ситуация:

Я хочу DropShadowEffect вокруг моего TreeViewItem, в то же время я хочу, чтобы TreeViewItem менял цвет при выборе.

Проблема:

Чтобы DropShadowEffect не применялось к тексту в TreeViewItem, мне нужно установить Background="White" на границе, которая содержит DropShadowEffect, кажется, это отменяет выделение TreeViewItem при выборе,

Я могу либо правильно применить DropShadowEffect, как в этом примере:

enter image description here

Или у меня может быть правильное выделение при выделении, но отбрасывает тень на текст, как в этом примере:

enter image description here

Вопрос:

Есть ли способ сохранить возможности выделенияTreeView, а также не допускайте применения DropShadowEffect к тексту в TreeViewItem?

Что я пробовал до сих пор:

  1. Я пытался установить Panel.ZIndex из TreeViewItem в стиле, который вы видите ниже, например <Setter Property="Panel.ZIndex" Value="5"/>.
  2. Я попытался использовать две рамки, которые занимают одинаковое пространство, как в этом уроке .

Дополнения:

Я не могу применить белый фон к TreeViewItem, потому что у меня есть рамка с закругленными краями вокруг нее, которая является идеально квадратным фоном TreeViewItem не соблюдается.

Я не хочу, чтобы DropShadowEffect применялся к кнопке Expander.

Минимальный (не-) рабочий пример:

TreeView:

<Window x:Class="TreeViewDropShadowExampl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TreeViewDropShadowExampl"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <TreeView ItemsSource="{Binding Root}" MinWidth="100" MinHeight="100">
        <TreeView.Resources>

            <HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Children}">
                <Grid>
                    <Border BorderBrush="Gray">
                        <TextBlock Text="{Binding ID}"/>
                        <Border.Effect>
                            <DropShadowEffect Color="Gray" BlurRadius="2"/>
                        </Border.Effect>
                    </Border>
                </Grid>             
            </HierarchicalDataTemplate>

            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="Margin" Value="2" />
            </Style>

        </TreeView.Resources>
    </TreeView>
</Window>

VM:

using System.Collections.ObjectModel;

namespace TreeViewDropShadowExampl
{
    class VM 
    {
        public VM()
        {
            var root = new Node("1");
            Root.Add(root);
            for (int i = 1; i < 4; i++)
            {
                Node newNode = new Node("1." + i.ToString());
                for (int j = 1; j < 4; j++)
                {
                    newNode.Children.Add(new Node("1." + i.ToString() + "." + j.ToString()));
                }
                root.Children.Add(newNode);
            }
        }

        public ObservableCollection<Node> Root { get; set; } = new ObservableCollection<Node>();
    }
}

Узел:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace TreeViewDropShadowExampl
{
    public class Node : INotifyPropertyChanged
    {
        #region WPF integration properties
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion WPF integration properties

        public Node(string id)
        {
            ID = id;
        }

        private string _id;
        public string ID
        {
            get { return _id; }
            set
            {
                _id = value;
                // Call OnPropertyChanged whenever the property is updated
                OnPropertyChanged();
            }
        }
        public ObservableCollection<Node> Children { get; set; } = new ObservableCollection<Node>();
    }
}

1 Ответ

0 голосов
/ 29 мая 2018

Вместо применения эффекта к Border внутри шаблона данных, примените эффект ко всему элементу:

<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Style.Triggers>
        <Trigger Property="IsSelected" Value="False">
          <Setter Property="Background" Value="White"/>
        </Trigger>
      </Style.Triggers>
      <Setter Property="Effect">
        <Setter.Value>
          <DropShadowEffect Color="Gray" BlurRadius="2"/>
        </Setter.Value>
      </Setter>
    </Style>
  </TreeView.ItemContainerStyle>
</TreeView>

Не забудьте удалить эффект из * 1005 вашего шаблона данных*.
Или даже полностью удалите Border, если он нужен только для эффекта тени.

Обновление:

Вы можете применить белый фонк товару тоже.Просто сделайте это в триггере, чтобы убедиться, что это происходит только тогда, когда элемент не выбран.

Обновление 2:

Имея все новые требования, вот полныйрешение вашей проблемы.

Прежде всего, возможно иметь закругленный прямоугольник выделения - вам просто нужно изменить стиль границы выделения.

<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <!-- This style changes the item's border appearance -->
      <Style.Resources>
        <Style TargetType="Border">
          <Setter Property="Effect">
            <Setter.Value>
              <DropShadowEffect Color="Gray" BlurRadius="2"/>
            </Setter.Value>
          </Setter>

          <!-- Set the same corner radius here as in your data template -->
          <Setter Property="CornerRadius" Value="8"/>
        </Style>
      </Style.Resources>
      <Setter Property="Margin" Value="2"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate>
      <Grid>
        <Border x:Name="RoundedBorder" CornerRadius="8">
          <!-- Your content here -->              
        </Border>            
      </Grid>             
      <HierarchicalDataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeViewItem}}" Value="False">
          <!-- Only setting the item's background when it's not selected -->
          <Setter TargetName="RoundedBorder" Property="Background" Value="White"/>
        </DataTrigger>
      </HierarchicalDataTemplate.Triggers>
    </HierarchicalDataTemplate>    
  </TreeView.ItemTemplate>
</TreeView>
...