我试着按照这里的例子:
WPF ListBox with self-removing items
这是有意义的,但我的问题是,ListView本身正在确定使用的模板。因此,它可以轻松地自定义绑定以指向正确的目标。然而,我正在使用MVVM并且正在努力使两者结合在一起。
示例,如果模板是:
<ListBox.ItemTemplate>
<DataTemplate>
<local:MyItemView/>
</DataTemplate>
</ListBox.ItemTemplate>
这突然变得更加困难,理想情况下,我希望在不对绑定进行硬编码的情况下重用该视图。
我尝试使用DependencyProperty
来传递List
和Element
,所以我可以通过命令将其删除。
<ListBox.ItemTemplate Name="myList">
<DataTemplate>
<local:MyItemView TheList={Binding ElementName=myList, Path=DataContext.List} TheElement={Binding}/>
</DataTemplate>
</ListBox.ItemTemplate>
但是,我遇到了绑定错误,告诉我它无法将TheElement
的值从MyClassViewModel
转换为MyClass
。即使我评论说TheList
总是为NULL。
基本上我想要:
class MyDataClass { // pretend there's more here}
class MyDataClassContainer
{
public ObservableCollection<MyDataClass> Items;
public void Add(MyDataClass);
public void Remove(MyDataClass);
}
class MyDataClassEntryViewModel
{
public static readonly DependencyProperty ListItemProperty = DependencyProperty.Register("TheClass", typeof(MyDataClass), typeof(MyDataClassEntryViewModel));
public static readonly DependencyProperty ListContainerProperty = DependencyProperty.Register("TheContainer", typeof(MyDataClassContainer), typeof(MyDataClassEntryViewModel));
public MyDataClass TheClass;
public MyDataClassContainer TheContainer;
public ICommand Delete = new DelegateCommand(RemoveItem);
private function RemoveItem(object parameter)
{
TheContainer.Remove(TheClass);
}
}
使用以下模板:
MyDataClassEntryView.xaml
<UserControl>
<Grid>
<Button Content="Delete" Command="{Binding Path=Delete}"/>
</Grid>
</UserControl>
MyDataContainerView.xaml
<UserControl>
<ListView x:Name="listView" ItemsSource="{Binding Path=Container.Items}">
<ListView.ItemTemplate>
<DataTemplate>
<local:MyDataClassEntryView TheClass="{Binding}" TheContainer="{Binding ElementName=listView, Path=DataContext.Container}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl>
注意:我省略了大多数多余的行,因为我试图得到一个我可以在任何地方使用的通用答案。不是硬编码的单一解决方案。我基本上想要保持MVVM结构强大,在后台没有大量的硬编码和布线。我想尽可能多地使用XAML。
我看到从列表中删除的所有其他方法都需要各种假设,例如使用SelectedIndex / Item,或者使用ContainerView本身的方法将元素作为参数进行投射,然后删除等等。简而言之,大多数解决方案都是根据给定的例子编写的。感觉应该有一种简单的方法来实现WPF。
由于ListView会自动创建我的子ViewModel / Views的实例,因此我无法显然获取任何数据。我只想基本上使用绑定传递参数。
答案 0 :(得分:1)
您的按钮应如下所示:
<Button Content="Delete"
Command="{Binding Path=Delete}"
CommandParameter="{Binding}/>
然后remove命令看起来像这样:
private function RemoveItem(object parameter)
{
var item = parameter as MyDataClass
if(item != null)
TheContainer.Remove(item);
}
您不需要将列表传递给ItemTemplate中的UserControl,因为它根本不需要知道列表
编辑: 我读了几遍你的问题,看看你对此感到困惑,所以我会试着澄清一下。
ListView是否在Xaml中设置了自己的模板,或者您使用另一个UserControl,datacontext仍会传递给该项目。无论您如何决定模板项目,ItemTemplate都将具有ListView项目列表中单个项目的datacontext。
我认为你的困惑在于外面的控制被引入模板。可以把它想象成运行程序时你带来的控件中的Xaml被剪切并粘贴到ListView的DataTemplate中,然后它与那里的硬编码没什么不同。
答案 1 :(得分:0)
您无法像使用过的那样使用Element绑定到达DataTemplate之外。
相反,你需要使用像这样的亲戚源。
<local:MyItemView TheList="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}, Path=DataContext.List}" />