我创建了一个从WPF ListBox派生的控件,它允许我通过拖放重新排序ListBox的内容。我使用以下代码执行此操作:
ListBox.Items.RemoveAt(sourceIndex);
ListBox.Items.Insert(targetIndex, droppedObject);
当我将ObservableCollection绑定到此派生类的ItemsSource时,会出现问题。绑定时,当我尝试访问ListBox.Item并编辑它时会抛出异常。它反而要我编辑ObservableCollection。这对我来说很有意义,但是我无法访问我派生的ListBox类的.cs文件中的这个集合。由于我的派生控件的实现应该是通用的,我不应该访问其中的全局ObservableCollection。我试图访问ListBox的ItemsSource并尝试对其进行更新,但我似乎无法将其转换为允许我在不知道内容是什么的情况下轻松编辑它的列表。我错过了这个问题的简单方法吗?
答案 0 :(得分:1)
但我似乎无法将其转换为允许我轻松编辑它而不知道内容是什么的列表
您需要确保分配给ItemsSource
属性的类型实际上支持对项目进行重新排序,即它实现了IList
接口。否则,您无法使用RemoveAt
和Insert
方法。
使用as
运算符进行投射:
var sourceCollection = ListBox.ItemsSource as IList;
if(sourceCollection != null)
{
sourceCollection.RemoveAt(sourceIndex);
sourceCollection.Insert(targetIndex, droppedObject);
}
如果您收到null
引用,则表示源集合未实现IList
接口,您无法根据索引移动项目。
答案 1 :(得分:0)
是的,正确的方法是实际重新排序基础ItemsSource中的项目。我的意思是,你可以强制ListView应用它自己的排序(例如将ItemsSource绑定到自定义的CollectionView),但是当底层集合发生变化时,事情会变得非常混乱。就个人而言,我会避开那条路。
正确的答案取决于您为什么要订购商品以及ViewModel和Model图层是否应该以某种方式对此重新排序做出反应(例如,将新商品布局保存到某处,以便在重新启动应用程序后它不会消失)。通常,ViewModel不应该监听ObservableCollections的更改,而是接受视图中的'MoveUp'/'MoveDown'命令并相应地改变ObservableCollection。
另一方面,如果你没有创建一个外部可重用的库,并且可以保证如果View开始实际在绑定集合周围移动项目时你的ViewModel不会吓到,那么只需将ItemsSource转换为非通用IList
接口,并按照您的建议直接操作项目。请注意,从理论上讲,绑定集合可能不会实现IList
,但在实际应用程序中它几乎肯定会实现。