c# - 从 ItemsControl 中删除项目

标签 c# wpf mvvm itemscontrol

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

5年前关闭。




Improve this question




我有一些 UserControls ItemsControl 的内部.

每个UserControl (在我的例子中称为 JobView)有一个 ContextMenu与 1 Item ('消除')。

现在当项目上UserControls ContextMenuClicked我想从 ItemsControlItemCollection 中删除它.

为此,我需要获取 Item , ContextMenu 被分配到。

目前我正在使用这个:

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);
}

它工作正常,但我很确定我必须有一些更好的解决方案。

我花了一些时间来解决这个问题,但我自己无法找到不同的解决方案。

我怎样才能得到 JobView使用 sender目的
或正在使用 sender在这种情况下完全错误?

最佳答案

将 ItemsControl 的 ItemsSource 绑定(bind)或设置为 UIElements 或 View 的 ObservableCollection 是错误的。至少如果您关心 MVVM 设计模式,这是推荐用于所有基于 XAML 的应用程序的模式。

您应该创建一个代表 JobView 状态的类并绑定(bind)到此类对象的 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>

有了这个,您就可以向 JobView 类添加一个 ICommand 属性,该属性绑定(bind)到从源集合中删除 Job 类的 View 模型的命令属性。请引用以下示例代码。

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 类,或者您可以使用 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 应用程序,我真的建议您学习它。

关于c# - 从 ItemsControl 中删除项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41428920/

相关文章:

c# - C# 应用程序中的堆栈溢出

c# - 托管在 IIS/Asp.NET 应用程序中的 HttpClient 证书不起作用

c# - "Server cannot accept argument"Azure VM 中 IIS 中的 FTP 服务器引发异常

c# - 为什么我们可以在 .NET 项目设置中更改平台,而平台无关?

c# - 在 Listbox 上使用自定义 DataTemplate 时,SelectedItem 绑定(bind)停止工作

c# - 如何创建自定义互斥体

wpf - 将 ListBox 绑定(bind)到另一个 ListBox

c# - wpf 中 OnPaintBackground 的替代方案。

c# - MVVMLight UserControl View 模型-为每个 View 创建用户控件的新实例

c# - 使用 WPF 和 MVVM 实现大型设置对话框的方法