从 ItemsControl 中删除项目
Remove item from ItemsControl
我在 ItemsControl
里面有一些 UserControls
。
每个 UserControl
(在我的例子中称为 JobView
)有一个 ContextMenu
和 1 Item
('Remove').
现在 UserControls ContextMenu
上的项目是 Clicked
我想将其从 ItemsControlItemCollection
中删除。
为此,我需要获取 Item
,上下文菜单已分配给。
目前我正在使用这个:
private void Item_Click(object sender, RoutedEventArgs e)
{
MenuItem item = (MenuItem)sender;
JobView view = null;
FrameworkElement currentObject = item;
while(1 == 1)
{
currentObject = currentObject.Parent as FrameworkElement;
if(currentObject.GetType() == typeof(System.Windows.Controls.Primitives.Popup))
{
view = (currentObject as System.Windows.Controls.Primitives.Popup).PlacementTarget as JobView;
break;
}
}
//Remove from ObservableCollection<JobView>:
JobViews.Remove(view);
}
它工作正常,但我很确定必须有更好的解决方案。
我花了一些时间来解决这个问题,但我自己无法找到不同的解决方案。
如何使用 sender
对象获取 JobView
或者在这种情况下使用 sender
完全错误?
将 ItemsControl 的 ItemsSource 绑定或设置为 UIElement 或视图的 ObservableCollection 是错误的。至少如果您关心 MVVM 设计模式,这是推荐用于所有基于 XAML 的应用程序的模式。
您应该创建一个 class 来表示您的 JobView 的状态并绑定到此类对象的 ObservableCollection,例如:
public class Job
{
}
public class JobViewModel
{
public ObservableCollection<Job> Jobs { get; } = new ObservableCollection<Job>()
{
new Job(),
new Job(),
new Job()
};
}
然后在 ItemsControl 的 ItemTemplate 中使用您的 UserControl (JobView):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new JobViewModel();
}
}
<ItemsControl ItemsSource="{Binding Jobs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:JobView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
有了这个,你就可以添加一个 ICommand 属性 到 JobView class,它绑定到视图模型的命令 属性,删除作业 class 来自源集合。请参考以下示例代码。
JobViewModel.cs:
public class JobViewModel
{
public JobViewModel()
{
RemoveCommand = new DelegateCommand<object>(argument =>
{
Jobs.Remove(argument as Job);
});
}
public ObservableCollection<Job> Jobs { get; } = new ObservableCollection<Job>()
{
new Job(),
new Job(),
new Job()
};
public DelegateCommand<object> RemoveCommand { get; }
}
JobView.xaml.cs:
public partial class JobView : UserControl
{
public JobView()
{
InitializeComponent();
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(JobView));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
}
JobView.xaml:
<UserControl x:Class="WpfApplication1.JobView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="uc">
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Command="{Binding PlacementTarget.Command, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"/>
</ContextMenu>
</UserControl.ContextMenu>
<Grid>
<TextBlock>job view...</TextBlock>
</Grid>
</UserControl>
MainWindow.xaml:
<ItemsControl ItemsSource="{Binding Jobs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:JobView Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
您需要自己实施 DelegateCommand class,或者您可以使用 Prism MVVM 库中可用的命令:https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/DelegateCommand.cs
可以使用 NuGet 安装 Prism:https://www.nuget.org/packages/Prism.Wpf/。
您可以在此处阅读有关 MVVM 模式的更多信息:https://msdn.microsoft.com/en-us/library/hh848246.aspx。如果您正在开发 XAML 应用程序,我真的建议您学习它。
我在 ItemsControl
里面有一些 UserControls
。
每个 UserControl
(在我的例子中称为 JobView
)有一个 ContextMenu
和 1 Item
('Remove').
现在 UserControls ContextMenu
上的项目是 Clicked
我想将其从 ItemsControlItemCollection
中删除。
为此,我需要获取 Item
,上下文菜单已分配给。
目前我正在使用这个:
private void Item_Click(object sender, RoutedEventArgs e)
{
MenuItem item = (MenuItem)sender;
JobView view = null;
FrameworkElement currentObject = item;
while(1 == 1)
{
currentObject = currentObject.Parent as FrameworkElement;
if(currentObject.GetType() == typeof(System.Windows.Controls.Primitives.Popup))
{
view = (currentObject as System.Windows.Controls.Primitives.Popup).PlacementTarget as JobView;
break;
}
}
//Remove from ObservableCollection<JobView>:
JobViews.Remove(view);
}
它工作正常,但我很确定必须有更好的解决方案。
我花了一些时间来解决这个问题,但我自己无法找到不同的解决方案。
如何使用 sender
对象获取 JobView
或者在这种情况下使用 sender
完全错误?
将 ItemsControl 的 ItemsSource 绑定或设置为 UIElement 或视图的 ObservableCollection 是错误的。至少如果您关心 MVVM 设计模式,这是推荐用于所有基于 XAML 的应用程序的模式。
您应该创建一个 class 来表示您的 JobView 的状态并绑定到此类对象的 ObservableCollection,例如:
public class Job
{
}
public class JobViewModel
{
public ObservableCollection<Job> Jobs { get; } = new ObservableCollection<Job>()
{
new Job(),
new Job(),
new Job()
};
}
然后在 ItemsControl 的 ItemTemplate 中使用您的 UserControl (JobView):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new JobViewModel();
}
}
<ItemsControl ItemsSource="{Binding Jobs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:JobView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
有了这个,你就可以添加一个 ICommand 属性 到 JobView class,它绑定到视图模型的命令 属性,删除作业 class 来自源集合。请参考以下示例代码。
JobViewModel.cs:
public class JobViewModel
{
public JobViewModel()
{
RemoveCommand = new DelegateCommand<object>(argument =>
{
Jobs.Remove(argument as Job);
});
}
public ObservableCollection<Job> Jobs { get; } = new ObservableCollection<Job>()
{
new Job(),
new Job(),
new Job()
};
public DelegateCommand<object> RemoveCommand { get; }
}
JobView.xaml.cs:
public partial class JobView : UserControl
{
public JobView()
{
InitializeComponent();
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(JobView));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
}
JobView.xaml:
<UserControl x:Class="WpfApplication1.JobView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="uc">
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Command="{Binding PlacementTarget.Command, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"/>
</ContextMenu>
</UserControl.ContextMenu>
<Grid>
<TextBlock>job view...</TextBlock>
</Grid>
</UserControl>
MainWindow.xaml:
<ItemsControl ItemsSource="{Binding Jobs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:JobView Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
您需要自己实施 DelegateCommand class,或者您可以使用 Prism MVVM 库中可用的命令:https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/DelegateCommand.cs
可以使用 NuGet 安装 Prism:https://www.nuget.org/packages/Prism.Wpf/。
您可以在此处阅读有关 MVVM 模式的更多信息:https://msdn.microsoft.com/en-us/library/hh848246.aspx。如果您正在开发 XAML 应用程序,我真的建议您学习它。