2016-03-10 68 views
0

我試圖在這裏效仿:如何在ItemTemplate是用戶控件時從ListView中正確刪除項目?

WPF ListBox with self-removing items

這是有道理的,但我的問題是,ListView控件本身是確定所使用的模板。所以它可以輕鬆地定製綁定指向正確的目標。然而,我正在使用MVVM,並且正在努力將兩者融合在一起。

例如,如果模板是:

<ListBox.ItemTemplate> 
     <DataTemplate> 
      <local:MyItemView/> 
     </DataTemplate> 
</ListBox.ItemTemplate> 

這突然變得更加困難,因爲理想情況下,我想重用沒有硬編碼綁定了這一觀點。

我試圖用DependencyProperty來通過ListElement,所以我可以通過命令刪除它。

<ListBox.ItemTemplate Name="myList"> 
     <DataTemplate> 
      <local:MyItemView TheList={Binding ElementName=myList, Path=DataContext.List} TheElement={Binding}/> 
     </DataTemplate> 
</ListBox.ItemTemplate> 

不過,我有綁定錯誤告訴我它無法從MyClassViewModel轉換值TheElementMyClass。即使我評論說總是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> 

注:I H AVE省略了大部分多餘的線條,因爲我試圖得到一個我可以在任何地方使用的通用答案。不是硬編碼的單一解決方案。我基本上想要保持MVVM結構強大,沒有大量的硬編碼和佈線在後臺。我想盡可能地使用XAML。

我所看到的從列表中移除的所有其他方法都需要各種假設,例如使用SelectedIndex/Item,或者使用ContainerView上的方法將元素作爲參數來投射它,然後刪除等等。簡而言之,大多數解決方案對於給定的例子來說太難編碼了。感覺就像在WPF中應該有一個簡單的方法來實現這一點。

由於ListView會自動創建我的子ViewModel/Views的實例,所以我不可能明顯得到任何數據。基本上,我只想使用綁定傳遞參數。

回答

0

你不能像使用過的那樣使用Element綁定到達DataTemplate的外部。

相反,你需要使用這樣的相對來源。

<local:MyItemView TheList="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}, Path=DataContext.List}" /> 
+0

嗯,即使如此,我仍然看到'null'在我的ViewModel – mGuv

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,因爲它根本不需要知道列表

編輯: 我幾次讀過你的問題,看看你對此感到困惑,所以我會試着澄清一下。

無論ListView在Xaml中設置自己的模板,還是使用其他UserControl,datacontext仍會傳遞給該項目。無論您如何決定對項目進行模板化,ItemTemplate都將具有ListView項目列表中單個項目的datacontext。

我認爲你的困惑來自外部的控件引入模板。可以把它看作是在運行程序時,將你帶入的控件的Xaml剪切並粘貼到ListView的DataTemplate中,然後它與在那裏進行硬編碼確實沒有區別。

+0

正確的,這是有道理的。我認爲我最初的問題是我通過模板用戶控件中的名稱來引用父元素。但是,我只能使用層次結構/祖先搜索。我現在唯一遇到的問題是,TheContainer仍然作爲null傳遞,我不知道爲什麼! – mGuv

+0

@mGuv在您發佈的代碼中永遠不會初始化它。確保在某個時候初始化它,通常是類構造函數 –

+0

以及我希望通過模板綁定它,但它不起作用。我如何通過構造函數來完成它,如果它由ListView自動調用的話?我沒有控制權將List傳遞給構造器? – mGuv

相關問題