【问题标题】:How to look for specific ListViewItem in a ListView - C# (WPF)如何在 ListView 中查找特定的 ListViewItem - C# (WPF)
【发布时间】:2019-10-28 20:08:55
【问题描述】:

我创建了包含三列的 ListView (C#-WPF):数字、操作和文件。首先,我向 ListView 添加了几个不同的项目,“数字”随着添加的每个条目而增加,“操作”正在记录到底发生了什么(移动/重命名/删除),“文件”列显示其中文件发生了一个动作。

XAML:

<ListView x:Name="ActionFile" HorizontalAlignment="center" Height="100" VerticalAlignment="bottom" Width="780" Margin="20,0,0,0">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Number" Width="40" DisplayMemberBinding="{Binding NumberX}"/>
            <GridViewColumn Header="Action" Width="200" DisplayMemberBinding="{Binding ActionX}"/>
            <GridViewColumn Header="File" Width="350" DisplayMemberBinding="{Binding FileX}"/>
        </GridView>
    </ListView.View>
</ListView>

C#:

public class FileActionEntry
{
    public int NumberX { get; set; }
    public string ActionX { get; set; }
    public string FileX { get; set; }
}
ActionFile.Items.Add(new FileActionEntry() { NumberX = numValue, ActionX = actionValue, FileX = fileValue });

现在,我正在尝试创建一个 foreach 循环,该循环将检查是否对特定文件执行了特定操作,然后从 ListView 中清除该条目并返回其“数字”值。我有几种不同的方法,但我不知道如何从项目中提取列值。我认为可以通过使用 '.SubItems' 来完成,但它似乎不适用于 WPF。

【问题讨论】:

  • 我怀疑 ListView 将ItemsSource 属性绑定到一个列表(或者更确切地说是 ObservableCollection)。在这里你没有那个。在我看来,您可以使用最好的 LINQ 轻松搜索 List&lt;FileActionEntry&gt;。

标签: c# wpf listview


【解决方案1】:

这样做的最佳方法是考虑将您的 listView ItemSource 绑定到 ObservableCollection,实现 INotifyPropertyChanged 接口,对该集合的任何更新都将自动反映在 UI 上。

考虑以下基于您的示例,其中在 TextBox 中提供文件名的条目从集合中删除:

Xaml

<Grid>
    <Grid VerticalAlignment="Top">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button Content="Process" Click="ButtonBase_OnClick"/>
        <TextBox Grid.Column="1" Margin="2" Text="{Binding SearchText, Mode=TwoWay}"/>
    </Grid>
    <ListView x:Name="ActionFile" HorizontalAlignment="center" Height="100" VerticalAlignment="bottom" Width="780" Margin="20,0,0,0" ItemsSource="{Binding FileActionEntryCollection}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Number" Width="40" DisplayMemberBinding="{Binding NumberX}"/>
                <GridViewColumn Header="Action" Width="200" DisplayMemberBinding="{Binding ActionX}"/>
                <GridViewColumn Header="File" Width="350" DisplayMemberBinding="{Binding FileX}"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

背后的代码

 public class FileActionEntry
{
    public int NumberX { get; set; }
    public string ActionX { get; set; }
    public string FileX { get; set; }
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private string _searchText = "";
    public string SearchText
    {
        get
        {
            return _searchText;
        }
        set
        {
            if (_searchText == value)
            {
                return;
            }

            _searchText = value;
            OnPropertyChanged();
        }
    }
    private ObservableCollection<FileActionEntry> _fileActionEntryCollection = new ObservableCollection<FileActionEntry>()
    {
        new FileActionEntry(){ ActionX = "Moved", FileX = "File1", NumberX = 1},
        new FileActionEntry(){ ActionX = "Renamed", FileX = "File2", NumberX = 2},
        new FileActionEntry(){ ActionX = "Removed", FileX = "File3", NumberX = 3}
    };


    public ObservableCollection<FileActionEntry> FileActionEntryCollection
    {
        get
        {
            return _fileActionEntryCollection;
        }

        set
        {
            if (_fileActionEntryCollection == value)
            {
                return;
            }

            _fileActionEntryCollection = value;
            OnPropertyChanged();
        }
    }

    public MainWindow()
    {
        InitializeComponent();

    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        if (FileActionEntryCollection.Any(f => f.FileX == SearchText))
            FileActionEntryCollection.Remove(FileActionEntryCollection.First(f => f.FileX == SearchText));
    }
}

【讨论】:

    【解决方案2】:

    您应该(必须)使用数据绑定 (Data Binding Overview in WPF)。这会让你的生活轻松很多。数据绑定上下文中的一个基本类是ObservableColllection。此集合将通知绑定目标任何更改(例如,添加或删除)。所有ItemsControl 喜欢ListView 的人都会听取这些变化,并将更新他们的视图以反映这些变化。所以你永远不需要直接访问控件来添加或删除项目。

    视图模型是绑定源:

    class ViewModel : INotifyPropertyChanged
    {
      // Ctor
      public ViewModel() => this.FileActionEntries = new ObservableCollection<FileActionEntry>();
    
      private void AddFileActionToListView()
      {
        var newFileEntry = new FileActionEntry() { NumberX = numValue, ActionX = actionValue, FileX = fileValue };
    
        // Add an item to the ListView
        // or any other control that binds to FileActionEntries (ObservableCollection)
        this.FileActionEntries.Add(newFileEntry);
      }
    
      private int CheckFileAction(string action, string file)
      {
        // Throws an exception if file not found
        FileActionEntry fileEntry = this.FileActionEntries.First(entry => entry.FileX.Equals(file, StringComparison.OrdinalIgnoreCase));
    
        // TODO: Check action
    
        // Remove an item from the ListView
        // or any other control that binds to FileActionEntries (ObservableCollection)
        this.FileActionEntries.Remove(fileEntry);
    
        return fileEntry.NumberX;
      }
    
      private ObservableCollection<FileActionEntry> fileActionEntries;
      public ObservableCollection<FileActionEntry> FileActionEntries
      {
        get => this.fileActionEntries;
        set 
        { 
          this.fileActionEntries = value; 
          OnPropertyChanged();
        }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    

    XAML 绑定 ItemsSource:

    <Window>
      <Window.DataContext>
        <ViewModel />
      </Window.DataContext>
    
      <ListView x:Name="ActionFile" 
                ItemsSource="{Binding FileActionEntries}" >
        <ListView.View>
          <GridView>
              <GridViewColumn Header="Number" Width="40" DisplayMemberBinding="{Binding NumberX}"/>
              <GridViewColumn Header="Action" Width="200" DisplayMemberBinding="{Binding ActionX}"/>
              <GridViewColumn Header="File" Width="350" DisplayMemberBinding="{Binding FileX}"/>
          </GridView>
        </ListView.View>
      </ListView>
    </Window>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      相关资源
      最近更新 更多