2017-01-02 185 views
-1

我在ItemsControl的内部有一些UserControls从ItemsControl中删除项目

每个UserControl(在我的情况下称为JobView)有一个ContextMenu与1 Item('删除')。

现在当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完全错误的在这种情况下?

回答

1

结合或一个ItemsControl的的ItemsSource设置UI元素或视图的一个ObservableCollection是错误的。至少如果你关心MVVM设计模式,这是所有基于XAML应用程序推荐的模式。

您应该创建一个类,它表示你的工作视图和绑定的状态,这样的对象的一个​​ObservableCollection,如:

public class Job 
{ 
} 

public class JobViewModel 
{ 
    public ObservableCollection<Job> Jobs { get; } = new ObservableCollection<Job>() 
    { 
     new Job(), 
     new Job(), 
     new Job() 
    }; 
} 

然后你用你的用户控件(工作视图)ItemsControl中的ItemTemplate:它

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属性,该属性绑定到从源集合中删除Job类的视图模型的命令属性。请参考下面的示例代码。

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类或者你可以使用棱镜MVVM库中提供了一个:https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/DelegateCommand.cs

可以利用的NuGet安装棱镜:https://www.nuget.org/packages/Prism.Wpf/

你可以阅读更多有关MVVM模式这里:https://msdn.microsoft.com/en-us/library/hh848246.aspx。如果你正在开发XAML应用程序,我真的建议你学习它。