通过 ListView WPF 进行迭代

问题描述 投票:0回答:1

从 Windows 窗体到 WPF 是一个挑战,这是我的第一个 WPF 项目,所以如果我遗漏了一些明显的东西,请原谅我......

我正在逐行向 ListView 添加项目,然后想稍后迭代这些项目并读取项目和子项目值。我尝试了几种方法,但都只返回最后一行。

我没有使用 ItemsSource 属性,因为我想在添加行时查看它们,因为在添加每行之前可能需要一些时间来处理每行的数据。如果我使用 ItemsSource = data,我必须等到获取所有数据,然后一次性添加所有数据,并且还没有找到使用该方法的另一种方法。

我在这里看了很多建议,这个看起来不错,但它使用 ItemsSource 一次性添加所有数据。 https://stackoverflow.com/questions/42635953/c-sharp-wpf-iterate-through-listview-items

我有这个代码

<ListView x:Name="listViewResults" Margin="2,117,4,36" Grid.ColumnSpan="6" FontFamily="Consolas" >
     <ListView.View>
         <GridView>
             <GridViewColumn Header="#"  Width="40" DisplayMemberBinding ="{Binding Path=hop}"/>
             <GridViewColumn Header="Host/IP" Width="350" DisplayMemberBinding ="{Binding Path=hostIP}"/>
             <GridViewColumn Header="RTT1" Width="100" DisplayMemberBinding ="{Binding Path=R1}"/>
             <GridViewColumn Header="RTT2" Width="100" DisplayMemberBinding ="{Binding Path=R2}"/>
             <GridViewColumn Header="RTT3" Width="100" DisplayMemberBinding ="{Binding Path=R3}"/>
             <GridViewColumn Header="Average" Width="100" DisplayMemberBinding ="{Binding Path=average}"/>

         </GridView>
     </ListView.View>
 </ListView>
public class RowData
{
    public string? hop { get; set; }
    public string? hostIP { get; set; }
    public string? R1 { get; set; }
    public string? R2 { get; set; }
    public string? R3 { get; set; }
    public string? average { get; set; }
    public string? tag { get; set; }
}

这就是我添加的方式,逐行添加...

RowData row = new RowData();
ListView lv = listViewResults;
lv.Items.Clear();

foreach (var entry in MyMethod(ipToTrace))
{
  row.hop = hopID;
  row.hostIP = hostOrIPAddress;
  row.R1 = roundTripTime[0];
  //etc...
  lv.Items.Add(row);
}

我已经尝试了所有这些方法来迭代 ListView 并且都返回唯一的最后一行

// 1
foreach (RowData item in listViewResults.Items)
{
    MessageBox.Show("Hop: " + item.hop + " IP: " + item.hostIP);
}

// 2
for (int i = 0; i < listViewResults.Items.Count; i++)
{
    RowData item = listViewResults.Items[i] as RowData;
    MessageBox.Show("Hop: " + item.hop + " IP: " + item.hostIP);
    
}

// 3
List<RowData> items = (List<RowData>)listViewResults.Items.Cast<RowData>().ToList();
foreach (RowData row in items)
{
    MessageBox.Show(row.hostIP + "    -   " + row.ToString());
}

当我查询 count 属性时,它总是具有正确的行数,但我真的很困惑为什么我只得到最后一条记录返回。

wpf listview
1个回答
0
投票

您对

ItemsControl.ItemsSoucre
属性及其使用方式的所有假设都是错误的。您永远不应该通过将项目添加到
ItemsSource
Items
属性来直接修改集合。相反,定义一个您正在处理的集合并将其分配给
ItemsSource
(最好使用数据绑定)。

您所要做的就是创建一个

ObservableCollection<T>
并将其分配给
ItemsSource
属性。现在,当向该集合添加/删除项目时,
ListView
将自动更新以显示更改。您使用相同的集合来迭代行。

请注意,常见的 C# 命名约定 要求所有公共成员都使用 PascalCase 而不是驼峰式命名。只有字段被命名为驼峰命名法,并且字段永远不会是公共的,除非它们是常量或事件。如果您决定不使用通用约定,那么您至少应该保持一致,并且不要混合命名规则(因为您的一些属性是 PascalCase 和一些 CamelCase)。

partial class MainWindow : Window
{
  // ObservableCollection implements INotifyCollectionChanged which enables 
  // every ItemsControl (like the ListView) to track changes of the ItemsSource.
  // Create a field or property.
  public ObservableCollection<RowData> Rows { get; }

  public MainWindow()
  {
    InitializeComponent();

    this.Rows = new ObservableCollection<RowData>();

    // Assign the collection to the ItemsSource property or use data binding
    listViewResults.ItemsSource = this.Rows;

    this.Loaded += OnLoaded;
  }

  private void OnLoaded(object sender, RoutedEventArgs e)
  {   
    foreach (var entry in MyMethod(ipToTrace))
    {
      RowData row = new RowData()
      {
        Hop = hopID,
        hostIP = hostOrIPAddress, 
        R1 = roundTripTime[0],
        //etc...
      }

      this.Rows.Add(row);
    }
  }

  private void ProcessRows()
  {
    // If you want to iterate over the rows, just use the source collection
    foreach (RowData row in this.Rows)
    {
      MessageBox.Show("Hop: " + row.hop + " IP: " + row.hostIP);
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.