TextDecorations не применяются к TextBlock во время триггера стиля TreeViewItem - PullRequest
2 голосов
/ 04 августа 2010

У меня есть приложение WPF, в котором я хотел бы украсить логически удаленные элементы (хранящиеся в TreeView), отображая их с помощью зачеркивания TextDecoration.

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

Вот пример кода, который воспроизводит проблему. Первый XAML:


 <Style TargetType="TreeViewItem">
  <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
  <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
  <EventSetter Event="TreeViewItem.MouseRightButtonDown" Handler="tvw_MouseRightButtonUp"/>
  <Style.Triggers>
   <DataTrigger Binding="{Binding IsDeleted}" Value="True">
    <!--<Setter Property="TextBlock.Foreground" Value="red" />-->
    <Setter Property="TextBlock.TextDecorations" Value="Underline" />
   </DataTrigger>
  </Style.Triggers>
 </Style>
</TreeView.Resources>

А вот и С #

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Globalization;

namespace StrikethroughTest {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            ObservableCollection<ViewModel> model = BuildModel();
            tvw.ItemsSource = model;
        }

        private ObservableCollection<ViewModel> BuildModel() {
            ObservableCollection<ViewModel> toplevel = new ObservableCollection<ViewModel>();
            ViewModel root = new ViewModel("Root");
            toplevel.Add(root);
            for (int i = 1; i < 5; ++i) {
                ViewModel child = new ViewModel("Child " + i);
                root.AddChild(child);
                for (int j = 1; j < 5; ++j) {
                    ViewModel leaf = new ViewModel("Leaf " + i + "," + j);
                    child.AddChild(leaf);
                }
            }
            return toplevel;
        }

        private void tvw_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
            ViewModel item = tvw.SelectedItem as ViewModel;
            if (item != null) {
                ShowMenu(item, tvw);
            }

        }

        private void ShowMenu(ViewModel item, FrameworkElement source) {
            ContextMenu menu = new ContextMenu();
            MenuItem mnuDelete = new MenuItem();
            mnuDelete.Header = "Delete";
            mnuDelete.Click += new RoutedEventHandler((src, e) => { item.IsDeleted = true; });
            menu.Items.Add(mnuDelete);
            source.ContextMenu = menu;
        }

    }

    public class ViewModel : ViewModelBase {

        private bool _expanded;
        private bool _selected;
        private bool _deleted;
        private ObservableCollection<ViewModel> _children;        

        public ViewModel(string caption) {
            this.Caption = caption;
            _children = new ObservableCollection<ViewModel>();
        }

        public void AddChild(ViewModel child) {
            _children.Add(child);
        }

        public bool IsExpanded {
            get { return _expanded; }
            set { SetProperty("IsExpanded", ref _expanded, value); }
        }

        public bool IsSelected {
            get { return _selected; }
            set { SetProperty("IsSelected", ref _selected, value); }
        }

        public bool IsDeleted {
            get { return _deleted; }
            set { SetProperty("IsDeleted", ref _deleted, value); }
        }

        public ObservableCollection<ViewModel> Children {
            get { return _children; }
        }


        public String Caption { get; set; }

    }

    public abstract class ViewModelBase : INotifyPropertyChanged {
        protected bool SetProperty<T>(string propertyName, ref T backingField, T value) {
            var changed = !EqualityComparer<T>.Default.Equals(backingField, value);
            if (changed) {
                backingField = value;
                RaisePropertyChanged(propertyName);
            }
            return changed;
        }

        protected void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

    }
}

Когда кто-то выбирает узел дерева, щелкает правой кнопкой мыши и выбирает Удалить, я хочу, чтобы заголовок был удален. В моем реальном приложении каждый TreeViewItem также имеет значок, который я для краткости опускаю, хотя, похоже, это не имеет значения.

У кого-нибудь есть идеи, почему это не работает?

1 Ответ

4 голосов
/ 04 августа 2010

Вы устанавливаете свойства для TreeViewItem. Настройка TextBlock.Foreground работает, потому что это свойство наследуемо (см. Свойство Значение Наследование ), поэтому TextBlock получит значение из своего родительского TreeViewItem. TextBlock.TextDecorations не наследуется, поэтому вам нужно установить его в самом TextBlock вместо TreeViewItem.

Самый простой способ сделать это, возможно, поместить триггер в DataTemplate, выполнив что-то вроде этого:

<TreeView.Resources>
    <Style TargetType="TreeViewItem">
        <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
        <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        <EventSetter Event="TreeViewItem.MouseRightButtonDown" Handler="tvw_MouseRightButtonUp"/>
    </Style>
    <HierarchicalDataTemplate DataType="{x:Type vm:ViewModel}" ItemsSource="{Binding Children}">
        <TextBlock Name="TextBlock" Text="{Binding Caption}"/>
        <HierarchicalDataTemplate.Triggers>
            <DataTrigger Binding="{Binding IsDeleted}" Value="True">
                <Setter TargetName="TextBlock" Property="TextDecorations" Value="Underline" />
            </DataTrigger>
        </HierarchicalDataTemplate.Triggers>
    </HierarchicalDataTemplate>
</TreeView.Resources>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...