我有一个WPF应用程序,我希望通过使用删除线TextDecoration显示逻辑删除的项目(在TreeView中保存)。
我可以在触发时获得样式触发器以成功应用Foreground颜色,但是当我尝试设置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也有一个图标,为简洁起见,我省略了它,虽然看起来没什么区别。
有没有人知道为什么这不起作用?
答案 0 :(得分:4)
您正在TreeViewItem上设置属性。设置TextBlock.Foreground是有效的,因为该属性是可继承的(请参阅Property Value Inheritance),因此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>