我有一个WPF应用程序,我想通过用删除线TextDecoration显示它们来装饰逻辑删除的项目(在TreeView中保存)。在TreeViewItem样式触发器中TextDecorations不应用于TextBlock
我可以在触发时成功应用前景色,但是当我尝试设置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>
这里是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;
}
}
当某人选择树节点时,右键单击并选择删除,我希望标题被删除。在我的真实应用程序中,每个TreeViewItem都有一个图标,为简洁起见我省略了它们,尽管它看起来没有什么区别。
有没有人有任何想法,为什么这不工作?
谢谢,完美的作品!我想我认为这是因为我用'TextBlock'为我的setter属性添加了前缀,它会以某种方式将它神奇地应用于与该类型匹配的TreeViewItem的所有后代子节点。我想我仍然有办法理解继承模型。感谢您的链接,我会去看看。 – David 2010-08-05 02:24:26