WPF - 从ItemsSource中删除项目的最佳方法

Tho*_*que 5 wpf itemscontrol itemssource

我正在编写一个自定义ItemsControl(标签式文档容器),当用户关闭它时,每个项目(选项卡)都可以从UI中删除.但是,我不能直接从ItemsControl.Items集合中删除它,因为这些项可以是数据绑定.所以,我必须从删除它ItemsSource,它可以是任何东西(ICollection,DataTable,DataSourceProvider...).

在我的应用程序的上下文中,我知道它的实际类型是什么ItemsSource,但我希望该控件更通用,以便我可以在以后重用它.

所以我正在寻找一种从数据源中删除项目的方法,而不知道它的类型.我可以使用反射,但感觉很脏......到目前为止,我想出的最佳解决方案是使用dynamic:

    internal void CloseTab(TabDocumentContainerItem tabDocumentContainerItem)
    {
        // TODO prompt user for confirmation (CancelEventHandler ?)

        var item = ItemContainerGenerator.ItemFromContainer(tabDocumentContainerItem);

        // TODO find a better way...
        try
        {
            dynamic items = ItemsSource;
            dynamic it = item;
            items.Remove(it);
        }
        catch(RuntimeBinderException ex)
        {
            Trace.TraceError("Oops... " + ex.ToString());
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我对此并不满意,我相信一定有更好的方法.任何建议,将不胜感激 !

Qua*_*ter 9

ItemCollection由归国ItemsControl.Items不会允许你直接调用删除,但它实现IEditableCollectionView并不会允许你调用该接口的Remove方法.

这仅在集合视图绑定到ItemsSource实现IEditableCollectionView自身时才有效.默认集合视图适用于大多数可变集合,但不适用于实现ICollection但不适用的对象IList.

IEditableCollectionView items = tabControl.Items; //Cast to interface
if (items.CanRemove)
{
    items.Remove(tabControl.SelectedItem);
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*que 2

好吧,我找到了解决方案...

  • 如果ItemsSource是数据绑定的,我要么引发一个事件(与代码隐藏一起使用),要么调用一个命令(与 ViewModel 一起使用)来从ItemsSource集合中删除该项目。

  • 如果不是数据绑定,我会引发一个事件来提示用户确认,然后直接从Items

    public static readonly DependencyProperty CloseTabCommandProperty =
        DependencyProperty.Register(
            "CloseTabCommand",
            typeof(ICommand),
            typeof(TabDocumentContainer),
            new UIPropertyMetadata(null));
    
    public ICommand CloseTabCommand
    {
        get { return (ICommand)GetValue(CloseTabCommandProperty); }
        set { SetValue(CloseTabCommandProperty, value); }
    }
    
    public event EventHandler<RequestCloseTabEventArgs> RequestCloseTab;
    public event EventHandler<TabClosingEventArgs> TabClosing;
    
    internal void CloseTab(TabDocumentContainerItem tabDocumentContainerItem)
    {
        if (ItemsSource != null) // Databound
        {
            object item = ItemContainerGenerator.ItemFromContainer(tabDocumentContainerItem);
            if (item == null || item == DependencyProperty.UnsetValue)
            {
                return;
            }
            if (RequestCloseTab != null)
            {
                var args = new RequestCloseTabEventArgs(item);
                RequestCloseTab(this, args);
            }
            else if (CloseTabCommand != null)
            {
                if (CloseTabCommand.CanExecute(item))
                {
                    CloseTabCommand.Execute(item);
                }
            }
        }
        else // Not databound
        {
            if (TabClosing != null)
            {
                var args = new TabClosingEventArgs(tabDocumentContainerItem);
                TabClosing(this, args);
                if (args.Cancel)
                    return;
            }
            Items.Remove(tabDocumentContainerItem);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)