2017-08-02 80 views
3

我試圖刪除我的列表視圖中的所有選中的項目,當我點擊刪除按鈕。 ListViewListView CheckBox數據綁定 - 刪除選中的項目

我看過IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected"在相當多的地方被提及,但我不知道如何將它與我已有的IsChecked綁定結合起來。

在我的代碼,這是拋出一個異常: lvStores.Items.Remove(item);

我進口結構如下CSV文件:
「ID」, 「姓名」,CheckedINT
例如
「1662」,「BØRSTER」,0 < - 其中1 =檢查,0 =未檢查。
「1658」, 「BØRSTER」,1

我在ListView在另一種方法中使用此遍歷所述數據:

// Loop through ListView 
    foreach (var item in lvStores.Items.OfType<Store>()) 
    { 
     // If 1 item in Listview is checked then 
     if (item.IsChecked == true) 
     { 
      blnOk = true; 
      return; 
     } 
    } 

XAML

<Window x:Class="CloneMacro.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:CloneMacro" 
     mc:Ignorable="d" 
     Title="Clone Macro" Height="348" Width="620.045" Closed="MainWindow_Closed" Icon="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\copy.png"> 
    <Grid Background="#FFDEDEDE" Margin="-1,0,-8,0" HorizontalAlignment="Left" Width="621"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Button x:Name="cmdNew" HorizontalAlignment="Left" Margin="39,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="New" Click="cmdNew_Click"> 
      <Image x:Name="imgNew" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\Generic_Document.png" RenderTransformOrigin="0.172,1.089"/> 
     </Button> 
     <Button x:Name="cmdOpen" HorizontalAlignment="Left" Margin="80,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Open" Click="cmdOpen_Click"> 
      <Image x:Name="imgOpen" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\folder_Open_32xLG.png"/> 
     </Button> 
     <Button x:Name="cmdSave" HorizontalAlignment="Left" Margin="121,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Save" Click="cmdSave_Click"> 
      <Image x:Name="imgSave" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\save_16xLG.png"/> 
     </Button> 
     <Button x:Name="cmdDelete" HorizontalAlignment="Left" Margin="235,36,0,0" VerticalAlignment="Top" Width="39" Height="40" Click="cmdDelete_Click"> 
      <Image x:Name="imgDelete" HorizontalAlignment="Left" Height="33" VerticalAlignment="Top" Width="32" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\action_Cancel_16xLG.png" ToolTip="Delete" RenderTransformOrigin="1.334,0.534"/> 
     </Button> 
     <Button x:Name="cmdNewStore" HorizontalAlignment="Left" Margin="275,36,0,0" VerticalAlignment="Top" Width="39" Height="40" Click="cmdNewStore_Click"> 
      <Image x:Name="imgNewStore" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\action_add_16xLG.png" ToolTip="Add New Store" RenderTransformOrigin="0.5,0.5"/> 
     </Button> 
     <Button x:Name="cmdExecute" HorizontalAlignment="Left" Margin="355,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Execute" Click="cmdExecute_Click"> 
      <Image x:Name="image" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="37" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\StatusAnnotations_Play_32xLG_color.png"/> 
     </Button> 
     <Button x:Name="cmdCancel" HorizontalAlignment="Left" Margin="395,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Cancel" Click="cmdCancel_Click"> 
      <Image x:Name="imgCancel" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\CancelApproval_32x32.png"/> 
     </Button> 
     <CheckBox x:Name="chOpenLastUsed" Content="Open Last Used File" Margin="456,48,0,0" VerticalAlignment="Top" Height="21" Width="147" HorizontalAlignment="Left"/> 
     <ListView x:Name="lvStores" HorizontalAlignment="Left" Height="161" Margin="39,98,0,0" VerticalAlignment="Top" Width="466"> 
      <ListView.View> 
       <GridView> 
        <GridView.Columns> 
         <GridViewColumn Header="ID" Width="Auto"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <CheckBox Content="{Binding sID}" IsChecked="{Binding IsChecked}"/> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
         <GridViewColumn Header="Name" Width="Auto" DisplayMemberBinding="{Binding Path=sName}"/> 
         <GridViewColumn Header="Import File" Width="Auto" DisplayMemberBinding="{Binding Path=sImportFile}"/> 
        </GridView.Columns> 
       </GridView> 
      </ListView.View> 
     </ListView> 
     <Label x:Name="lblProgress" x:FieldModifier="public" Content="Status Text" HorizontalAlignment="Left" Margin="40,264,0,0" VerticalAlignment="Top" Width="465" BorderThickness="1" BorderBrush="#FF7C7C7C"/> 
     <Button x:Name="ComDialog" HorizontalAlignment="Left" Margin="533,152,0,0" VerticalAlignment="Top" Width="48" Height="51"> 
      <Image x:Name="imgComDialog" HorizontalAlignment="Left" Height="44" VerticalAlignment="Top" Width="48" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\DialogID_6220_32x.png"/> 
     </Button> 
    </Grid> 
</Window> 

CS

public MainWindow() 
    { 
     // Leave this to show the UI 
     InitializeComponent(); 

     lblProgress.Content = ""; 


     lvStores.ItemsSource = ReadCSV(@"C:\Users\Niclas VMWare\Downloads\TESTFILE.pcf"); 

    } 

    // Fill ListView 
    public class Store 
    { 
     public string sName { get; set; } 
     public string sImportFile { get; set; } 
     public string sID { get; set; } 
     public bool IsChecked { get; set; } 

     public Store(string id, string strName, string isChecked, string strImportFile) 
     { 
      sName = strName.Replace("\"",""); 
      sImportFile = Path.GetFileName(strImportFile); 
      sID = id.Replace("\"",""); 

      // Convert isChecked to boolean 
      // Do convertion outside the constructor to avoid any exception within 
      int iBool = Convert.ToInt32(isChecked); 

      switch (iBool) 
      { 
       case 0: IsChecked = false; break; 
       case 1: IsChecked = true; break; 
       default: throw new InvalidOperationException("Third value in PCF file must be 0 or 1!"); 
      } 
     } 
    } 
    public IEnumerable<Store> ReadCSV(string fileName) 
    { 
     // Make sure the file extension is pcf 
     string[] lines = File.ReadAllLines(Path.ChangeExtension(fileName, ".pcf").Replace("\"", ""), Encoding.GetEncoding(65001)); 

     // lines.Select allows to project each line as a Store 
     // This will give an IEnumerable<Store> back. 
     return lines.Select(line => 
     { 
      string[] data = line.Split(','); 
      // Return the store data 
      // Return id, Name, isChecked (chkbox checked?), filename 
      return new Store(data[0], data[1], data[2], fileName); 
     }); 
    } 
    // End Fill ListView 

    private void cmdDelete_Click(object sender, RoutedEventArgs e) 
    { 
     // if selected 
     foreach (var item in lvStores.Items.OfType<Store>()) 
     { 
      if (item.IsChecked == true) 
      { 
       lvStores.Items.Remove(item); 
      } 
     } 
    } 
+3

原因'IsChecked'綁定沒有作出意義是因爲你沒有遵循MVVM。你真的*應該學習並在你的WPF解決方案中實現它。一旦你這樣做,你可以在'IsChecked' viewmodel屬性上聽'PropertyChanged',並從'ObservableCollection'中移除它。 – Maverik

+0

拋出哪個異常? – Yevgeniy

+0

PresentationFramework.dll中發生類型爲「System.InvalidOperationException」的異常,但未在用戶代碼中處理 附加信息:在ItemsSource正在使用時操作無效。改爲使用ItemsControl.ItemsSource訪問和修改元素。 – Niclas

回答

2

我想:

  1. 使用一個ObservableCollection
  2. 上執行INotifyPropertyChanged您 存儲類(或類似的東西......其他人所說,正確,對MVVM模式讀了)。前兩個必須確保您的UI在運行時更新對象。
  3. 按 反向順序遍歷循環,並根據需要逐個刪除每個項目。

MainWindow.xaml:

<Window x:Class="CloneMacro.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:CloneMacro" 
     mc:Ignorable="d" 
     Title="Clone Macro" Height="348" Width="620.045"> 
    <Grid Background="#FFDEDEDE" Margin="-1,0,-8,0" HorizontalAlignment="Left" Width="621"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Button x:Name="cmdNew" HorizontalAlignment="Left" Margin="39,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="New" > 
      New 
     </Button> 
     <Button x:Name="cmdOpen" HorizontalAlignment="Left" Margin="80,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Open" Click="cmdOpen_Click"> 
      Open 
     </Button> 
     <Button x:Name="cmdSave" HorizontalAlignment="Left" Margin="121,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Save"> 
      Save 
     </Button> 
     <Button x:Name="cmdDelete" HorizontalAlignment="Left" Margin="235,36,0,0" VerticalAlignment="Top" Width="39" Height="40" Click="cmdDelete_Click"> 
      Delete 
     </Button> 
     <Button x:Name="cmdNewStore" HorizontalAlignment="Left" Margin="275,36,0,0" VerticalAlignment="Top" Width="39" Height="40"> 
      New Store 
     </Button> 
     <Button x:Name="cmdExecute" HorizontalAlignment="Left" Margin="355,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Execute"> 
      Execute 
     </Button> 
     <Button x:Name="cmdCancel" HorizontalAlignment="Left" Margin="395,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Cancel"> 
      Cancel 
     </Button> 
     <CheckBox x:Name="chOpenLastUsed" Content="Open Last Used File" Margin="456,48,0,0" VerticalAlignment="Top" Height="21" Width="147" HorizontalAlignment="Left"/> 
     <ListView x:Name="lvStores" HorizontalAlignment="Left" Height="161" Margin="39,98,0,0" VerticalAlignment="Top" Width="466"> 
      <ListView.View> 
       <GridView> 
        <GridView.Columns> 
         <GridViewColumn Header="ID" Width="Auto"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <CheckBox Content="{Binding sID}" IsChecked="{Binding IsChecked}"/> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
         <GridViewColumn Header="Name" Width="Auto" DisplayMemberBinding="{Binding Path=sName}"/> 
         <GridViewColumn Header="Import File" Width="Auto" DisplayMemberBinding="{Binding Path=sImportFile}"/> 
        </GridView.Columns> 
       </GridView> 
      </ListView.View> 
     </ListView> 
     <Label x:Name="lblProgress" x:FieldModifier="public" Content="Status Text" HorizontalAlignment="Left" Margin="40,264,0,0" VerticalAlignment="Top" Width="465" BorderThickness="1" BorderBrush="#FF7C7C7C"/> 
     <Button x:Name="ComDialog" HorizontalAlignment="Left" Margin="533,152,0,0" VerticalAlignment="Top" Width="48" Height="51"> 
      Dialog 
     </Button> 
    </Grid> 
</Window> 

MainWindow.xaml.cs:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace CloneMacro 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     ObservableCollection<Store> stores; 

     internal const string TESTFILE = @"C:\Temp\TESTFILE.pcf"; 
     public MainWindow() 
     { 
      // Leave this to show the UI 
      InitializeComponent(); 

      lblProgress.Content = ""; 

      OpenFile(TESTFILE); 
     } 

     internal void OpenFile(string fileName) 
     { 
      stores = ReadCSV(TESTFILE); 
      lvStores.ItemsSource = stores; 
     } 

     // Fill ListView 
     public class Store : INotifyPropertyChanged 
     { 
      public event PropertyChangedEventHandler PropertyChanged; 
      protected void OnPropertyChanged(string name) 
      { 
       PropertyChangedEventHandler handler = PropertyChanged; 
       if (handler != null) 
       { 
        handler(this, new PropertyChangedEventArgs(name)); 
       } 
      } 

      public string sName { get; set; } 
      public string sImportFile { get; set; } 
      public string sID { get; set; } 

      private bool isChecked; 
      public bool IsChecked 
      { 
       get { return isChecked; } 
       set 
       { 
        if (isChecked != value) 
        { 
         isChecked = value; 
         OnPropertyChanged("IsChecked"); 
        } 
       } 
      } 

      public Store(string id, string strName, string isChecked, string strImportFile) 
      { 
       sName = strName.Replace("\"", ""); 
       sImportFile = System.IO.Path.GetFileName(strImportFile); 
       sID = id.Replace("\"", ""); 

       // Convert isChecked to boolean 
       // Do convertion outside the constructor to avoid any exception within 
       int iBool = Convert.ToInt32(isChecked); 

       switch (iBool) 
       { 
        case 0: IsChecked = false; break; 
        case 1: IsChecked = true; break; 
        default: throw new InvalidOperationException("Third value in PCF file must be 0 or 1!"); 
       } 
      } 
     } 

     public ObservableCollection<Store> ReadCSV(string fileName) 
     { 
      // Make sure the file extension is pcf 
      string [] lines = File.ReadAllLines(
       System.IO.Path.ChangeExtension(fileName, ".pcf").Replace("\"", ""), Encoding.GetEncoding(65001)); 

      // lines.Select allows to project each line as a Store 
      // This will give an IEnumerable<Store> back. 
      var enumerable = lines.Select(line => 
      { 
       string [] data = line.Split(','); 
       // Return the store data 
       // Return id, Name, isChecked (chkbox checked?), filename 
       return new Store(data [0], data [1], data [2], fileName); 
      }); 

      stores = new ObservableCollection<Store>(); 
      foreach (var item in enumerable) 
      { 
       stores.Add(item); 
      } 
      return stores; 
     } 
     // End Fill ListView 

     private void cmdDelete_Click(object sender, RoutedEventArgs e) 
     { 
      for (int i = stores.Count - 1; i >= 0; i--) 
      { 
       if (stores[i].IsChecked) 
       { 
        stores.RemoveAt(i); 
       } 
      } 
     } 

     private void cmdOpen_Click(object sender, RoutedEventArgs e) 
     { 
      OpenFile(TESTFILE); 
     } 

    } 
} 

TESTFILE.pcf:

"1662","BØRSTER",0 
"1658","BØRSTER",1 
"1669","A Møøse once bit my sister.",1 
+0

謝謝,它完美的作品。您沒有更改XAML中的任何內容?你介意在你的代碼中加入一些評論嗎?我將開始閱讀MVVM :-) – Niclas

+0

@Niclas這是正確的方式進行您的要求。我將刪除我的答案,因爲它不適用。 –

+0

@Niclas,我沒有真正改變你發佈的代碼中的XAML,除了刪除一些本地機器路徑的圖像文件。就代碼中的評論...這將花費額外的費用。 :)如果你有任何問題的具體問題。 –