Hi, I have a WPF application in which I would like to decorate logically deleted items (held in a TreeView) by displaying them with the Strikethrough TextDecoration.
I can get the style trigger to successfully apply a Foreground color when fired, but when I try to set the TextDecorations it has no effect.
Here is some sample code that reproduces the problem. First the 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>
And here is the c#
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;
}
}
When someone selects a tree node, right clicks and selects Delete, I want the caption to be striked out. In my real app, each TreeViewItem also has an icon, which I omitted for brevity, although it appears to make no difference.
Does anyone have any ideas why this isn't working?