C# ListBoxItem';s模板的样式导致在删除项后激发EventTrigger
编辑:我发现问题在于参考资料中的C# ListBoxItem';s模板的样式导致在删除项后激发EventTrigger,c#,.net,wpf,storyboard,eventtrigger,C#,.net,Wpf,Storyboard,Eventtrigger,编辑:我发现问题在于参考资料中的ListBoxItem的样式。如果我对它进行评论,它可以正常工作。但它有什么问题?我想用蓝色选项覆盖默认样式的ListBoxItem,等等 我有一个列表框,其中项目模板包含一个边框。边框具有触发器,使删除按钮仅出现在鼠标悬停时。现在在DeleteCommandcommand中发生的是,我删除了列表框中显示此特定项的数据。因此,边框消失,但仍会调用MouseLeave触发器,我得到以下异常: Exception type: System.InvalidOperati
ListBoxItem
的样式。如果我对它进行评论,它可以正常工作。但它有什么问题?我想用蓝色选项覆盖默认样式的ListBoxItem
,等等
我有一个列表框
,其中项目模板包含一个边框
。边框具有触发器,使删除按钮仅出现在鼠标悬停时。现在在DeleteCommand
command中发生的是,我删除了列表框中显示此特定项的数据。因此,边框消失,但仍会调用MouseLeave
触发器,我得到以下异常:
Exception type: System.InvalidOperationException
Exception message: 'controlBox' name cannot be found in the name scope of 'System.Windows.Controls.Border'.
Exception stack trace:
at System.Windows.Media.Animation.Storyboard.ResolveTargetName(String targetName, INameScope nameScope, DependencyObject element)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containingObject, INameScope nameScope, HandoffBehavior handoffBehavior, Boolean isControllable, Int64 layer)
at System.Windows.Media.Animation.BeginStoryboard.Begin(DependencyObject targetObject, INameScope nameScope, Int64 layer)
at System.Windows.EventTrigger.EventTriggerSourceListener.Handler(Object sender, RoutedEventArgs e)
...
这是一个XAML示例:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<local:MyItems x:Key="myItems">
<local:MyItem Name="Item 1" />
<local:MyItem Name="Item 2" />
<local:MyItem Name="Item 3" />
</local:MyItems>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter Margin="0,0,0,4" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{StaticResource myItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" Padding="5" BorderBrush="Blue" BorderThickness="1">
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="controlBox" Storyboard.TargetProperty="Opacity" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="controlBox" Storyboard.TargetProperty="Opacity" To="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" />
<StackPanel Grid.Column="1" x:Name="controlBox" Opacity="0">
<Button Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MainWindow}}}"
CommandParameter="{Binding}">Delete</Button>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
删除
这是后面的示例代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ICommand DeleteCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
DeleteCommand = new MyCommand<MyItem>( Delete );
}
private void Delete( MyItem myItem )
{
MyItems myItems = Resources[ "myItems" ] as MyItems;
myItems.Remove( myItem );
}
}
public class MyItem : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( string ), typeof( MyItem ) );
public string Name { get { return (string) GetValue( NameProperty ); } set { SetValue( NameProperty, value ); } }
}
public class MyItems : ObservableCollection<MyItem>
{
}
public class MyCommand<T> : ICommand
{
private readonly Action<T> executeMethod = null;
private readonly Predicate<T> canExecuteMethod = null;
public MyCommand( Action<T> execute )
: this( execute, null )
{
}
public MyCommand( Action<T> execute, Predicate<T> canExecute )
{
executeMethod = execute;
canExecuteMethod = canExecute;
}
public event EventHandler CanExecuteChanged;
public void NotifyCanExecuteChanged( object sender )
{
if( CanExecuteChanged != null )
CanExecuteChanged( sender, EventArgs.Empty );
}
public bool CanExecute( object parameter )
{
return canExecuteMethod != null && parameter is T ? canExecuteMethod( (T) parameter ) : true;
}
public void Execute( object parameter )
{
if( executeMethod != null && parameter is T )
executeMethod( (T) parameter );
}
}
}
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Animation;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MyItem _itemToDelete;
public ICommand DeleteCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
DeleteCommand = new MyCommand<MyItem>(Delete);
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var fadeOutStoryBoard = TryFindResource("fadeOut");
if (fadeOutStoryBoard != null && fadeOutStoryBoard is Storyboard)
{
(fadeOutStoryBoard as Storyboard).Completed += fadeOutStoryBoard_Completed;
}
}
void fadeOutStoryBoard_Completed(object sender, EventArgs e)
{
if (this._itemToDelete != null)
{
MyItems myItems = Resources["myItems"] as MyItems;
myItems.Remove(this._itemToDelete);
}
}
private void Delete(MyItem myItem)
{
this._itemToDelete = myItem;
}
}
public class MyItem : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(MyItem));
public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } }
}
public class MyItems : ObservableCollection<MyItem>
{
}
public class MyCommand<T> : ICommand
{
private readonly Action<T> executeMethod = null;
private readonly Predicate<T> canExecuteMethod = null;
public MyCommand(Action<T> execute)
: this(execute, null)
{
}
public MyCommand(Action<T> execute, Predicate<T> canExecute)
{
executeMethod = execute;
canExecuteMethod = canExecute;
}
public event EventHandler CanExecuteChanged;
public void NotifyCanExecuteChanged(object sender)
{
if (CanExecuteChanged != null)
CanExecuteChanged(sender, EventArgs.Empty);
}
public bool CanExecute(object parameter)
{
return canExecuteMethod != null && parameter is T ? canExecuteMethod((T)parameter) : true;
}
public void Execute(object parameter)
{
if (executeMethod != null && parameter is T)
executeMethod((T)parameter);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WpfApplication2
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
公共ICommand DeleteCommand{get;private set;}
公共主窗口()
{
初始化组件();
DeleteCommand=新的MyCommand(删除);
}
私有无效删除(MyItem MyItem)
{
MyItems MyItems=资源[“MyItems”]作为MyItems;
myItems.Remove(myItem);
}
}
公共类MyItem:DependencyObject
{
public static readonly dependencProperty NameProperty=dependencProperty.Register(“Name”、typeof(string)、typeof(MyItem));
公共字符串名称{get{return(string)GetValue(NameProperty);}set{SetValue(NameProperty,value);}
}
公共类MyItems:ObservableCollection
{
}
公共类MyCommand:ICommand
{
私有只读操作executeMethod=null;
私有只读谓词canExecuteMethod=null;
公共MyCommand(操作执行)
:此(执行,空)
{
}
公共MyCommand(操作执行,谓词canExecute)
{
executeMethod=执行;
canExecuteMethod=canExecute;
}
公共事件处理程序CanExecuteChanged;
public void NotifyCanExecuteChanged(对象发送方)
{
如果(CanExecuteChanged!=null)
CanExecuteChanged(发送方,EventArgs.Empty);
}
公共布尔CanExecute(对象参数)
{
return canExecuteMethod!=null&参数为T?canExecuteMethod((T)参数):true;
}
public void Execute(对象参数)
{
if(executeMethod!=null&&参数为T)
executeMethod((T)参数);
}
}
}
序列图像板动画将保留对项目的引用,直到动画完成
您应该执行以下操作:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ICommand DeleteCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
DeleteCommand = new MyCommand<MyItem>( Delete );
}
private void Delete( MyItem myItem )
{
MyItems myItems = Resources[ "myItems" ] as MyItems;
myItems.Remove( myItem );
}
}
public class MyItem : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( string ), typeof( MyItem ) );
public string Name { get { return (string) GetValue( NameProperty ); } set { SetValue( NameProperty, value ); } }
}
public class MyItems : ObservableCollection<MyItem>
{
}
public class MyCommand<T> : ICommand
{
private readonly Action<T> executeMethod = null;
private readonly Predicate<T> canExecuteMethod = null;
public MyCommand( Action<T> execute )
: this( execute, null )
{
}
public MyCommand( Action<T> execute, Predicate<T> canExecute )
{
executeMethod = execute;
canExecuteMethod = canExecute;
}
public event EventHandler CanExecuteChanged;
public void NotifyCanExecuteChanged( object sender )
{
if( CanExecuteChanged != null )
CanExecuteChanged( sender, EventArgs.Empty );
}
public bool CanExecute( object parameter )
{
return canExecuteMethod != null && parameter is T ? canExecuteMethod( (T) parameter ) : true;
}
public void Execute( object parameter )
{
if( executeMethod != null && parameter is T )
executeMethod( (T) parameter );
}
}
}
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Animation;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MyItem _itemToDelete;
public ICommand DeleteCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
DeleteCommand = new MyCommand<MyItem>(Delete);
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var fadeOutStoryBoard = TryFindResource("fadeOut");
if (fadeOutStoryBoard != null && fadeOutStoryBoard is Storyboard)
{
(fadeOutStoryBoard as Storyboard).Completed += fadeOutStoryBoard_Completed;
}
}
void fadeOutStoryBoard_Completed(object sender, EventArgs e)
{
if (this._itemToDelete != null)
{
MyItems myItems = Resources["myItems"] as MyItems;
myItems.Remove(this._itemToDelete);
}
}
private void Delete(MyItem myItem)
{
this._itemToDelete = myItem;
}
}
public class MyItem : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(MyItem));
public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } }
}
public class MyItems : ObservableCollection<MyItem>
{
}
public class MyCommand<T> : ICommand
{
private readonly Action<T> executeMethod = null;
private readonly Predicate<T> canExecuteMethod = null;
public MyCommand(Action<T> execute)
: this(execute, null)
{
}
public MyCommand(Action<T> execute, Predicate<T> canExecute)
{
executeMethod = execute;
canExecuteMethod = canExecute;
}
public event EventHandler CanExecuteChanged;
public void NotifyCanExecuteChanged(object sender)
{
if (CanExecuteChanged != null)
CanExecuteChanged(sender, EventArgs.Empty);
}
public bool CanExecute(object parameter)
{
return canExecuteMethod != null && parameter is T ? canExecuteMethod((T)parameter) : true;
}
public void Execute(object parameter)
{
if (executeMethod != null && parameter is T)
executeMethod((T)parameter);
}
}
}
使用系统;
使用System.Collections.ObjectModel;
使用System.Windows;
使用System.Windows.Input;
使用System.Windows.Media.Animation;
命名空间WpfApplication2
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
私有MyItem _itemToDelete;
公共ICommand DeleteCommand{get;private set;}
公共主窗口()
{
初始化组件();
DeleteCommand=新的MyCommand(删除);
this.Loaded+=主窗口\u Loaded;
}
已加载无效主窗口(对象发送器、路由目标)
{
var fadeOutStoryBoard=TryFindResource(“fadeOut”);
if(fadeOutStoryBoard!=null&&fadeOutStoryBoard是情节提要)
{
(作为故事板的淡出托里板)。已完成+=淡出托里板\u已完成;
}
}
void fadeOutStoryBoard_已完成(对象发送方,事件参数e)
{
if(this.\u itemtodelet!=null)
{
MyItems MyItems=资源[“MyItems”]作为MyItems;
myItems.Remove(此.\u itemToDelete);
}
}
私人vo