WPF-从ItemsSource删除项目的最佳方法 [英] WPF - Best way to remove an item from the 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());
}
}
但是我对此并不满意,我敢肯定必须有更好的方法.任何建议,将不胜感激!
好的,我找到了解决方法...
-
如果
ItemsSource
是数据绑定的,则我引发一个事件(供隐藏代码使用)或调用命令(供ViewModel使用)以从ItemsSource
集合中删除该项目. /p> -
如果未绑定数据,则引发一个事件以提示用户进行确认,然后直接从
中删除容器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); } }
I'm writing a custom ItemsControl
(a tabbed document container), where each item (tab) can remove itself from the UI when the user closes it. However, I can't remove it directly from the ItemsControl.Items
collection, because the items can be databound. So I have to remove it from the ItemsSource
, which can be anything (ICollection
, DataTable
, DataSourceProvider
...).
In the context of my application, I know what the actual type of the ItemsSource
will be, but I want that control to be more generic so that I can reuse it later.
So I'm looking for a way to remove an item from a data source, without knowing its type. I could use reflection, but it feels dirty... So far the best solution I came up with is using 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());
}
}
But I'm not really happy with it, I'm sure there must be a better way. Any suggestions would be appreciated !
OK, I found a solution...
If the
ItemsSource
is databound, I either raise an event (for use with code-behind) or invoke a command (for use with a ViewModel) to remove the item from theItemsSource
collection.If it's not databound, I raise an event to prompt the user for confirmation, and I remove the container directly from
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); } }
这篇关于WPF-从ItemsSource删除项目的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!