【问题标题】:C# WPF OnPropertyChanged Within a foreach loopC# WPF OnPropertyChanged 在 foreach 循环中
【发布时间】:2010-12-01 14:12:30
【问题描述】:

我一直在努力学习和利用 WPF 和数据绑定。我有一个列表视图,其中有一列将显示三个图像之一,如下面的 sn-p 所示:

<GridViewColumn Header="Status" Width="50">
  <GridViewColumn.CellTemplate>
    <DataTemplate>
      <Image x:Name="TheImage" Height="18"/>
        <DataTemplate.Triggers>
          <DataTrigger Binding="{Binding Path=Status}" Value="queued">
            <Setter TargetName="TheImage" Property="Source" Value="Images\que_48.png" />
          </DataTrigger>
          <DataTrigger Binding="{Binding Path=Status}" Value="completed">
            <Setter TargetName="TheImage" Property="Source" Value="Images\complete_48.png" />
          </DataTrigger>
          <DataTrigger Binding="{Binding Path=Status}" Value="failed">
            <Setter TargetName="TheImage" Property="Source" Value="Images\fail_48.png" />
          </DataTrigger>
        </DataTemplate.Triggers>
      </DataTemplate>
    </GridViewColumn.CellTemplate>
  </GridViewColumn>

我有一个类 (BatchQueueItem),其中包含用于处理 PropertyChange 事件的代码:

public string status;
  public string Status
  {
    get { return status; }
    set 
    { 
      status = value;
      OnPropertyChanged("Status");
    }            
  }
  // Create the OnPropertyChanged method to raise the event

  public event PropertyChangedEventHandler PropertyChanged;    
  private void OnPropertyChanged(string status)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(status));
    }
  }

我在列表视图窗口页面上有一个按钮:

private void btnStart_Click(object sender, RoutedEventArgs e)
{
  foreach (var item in listView1.Items)
  {
    BatchQueueItem bqi = (BatchQueueItem)item;
    string currFile = bqi.CurrFile;
    if (mainWindow.isIsbnInFileName(ref currFile))
    {
       bqi.Status = "completed";
    }
    else
    {
      bqi.Status = "failed";
    }
  }
}

我遇到的问题是图像直到 foreach 循环完成并且 btnStart_Click() 方法完成后才会更新。一旦发生这种情况,所有图像都会按预期更新,而不是迭代地一次更新。

我想要并且我认为会发生的事情是,foreach 循环的每次迭代都会更新相应行的图像。毫无疑问,我错过了关于这一切如何运作的重要信息。有什么建议吗?

【问题讨论】:

    标签: c# wpf listview inotifypropertychanged


    【解决方案1】:

    我遇到的问题是图像直到 foreach 循环完成并且 btnStart_Click() 方法完成后才会更新。一旦发生这种情况,所有图像都会按预期更新,而不是迭代地一次更新。

    我想要并且我认为会发生的事情是,foreach 循环的每次迭代都会更新相应行的图像。毫无疑问,我错过了关于这一切如何运作的重要信息。有什么建议吗?

    这是你如何更新的问题。

    问题不在于 UI 没有更新 - 在内部,它确实更新了。问题是您正在主 UI 线程上执行此更新和 foreach 循环。当您执行此操作时,UI 将被完全阻止(并且不会刷新/重绘),直到您的操作 100% 完成,并且消息泵可以再次运行。

    有一些选项可以解决这个问题 - 如果您的操作需要一段时间,并且您希望它在运行时更新,您可以将 foreach 循环移动到在后台线程上运行的委托中。然后,您将使用 Dispatcher 将状态更新调用回 UI 线程。

    当您进行长时间运行时,这有几个好处:

    1. 您可以在 UI 中获取实例反馈/状态
    2. 您的 UI 在您的操作运行时保持响应。

    【讨论】:

    • 其实这里不需要使用 Dispatcher.Invoke :WPF 会自动跨线程封送 PropertyChanged 通知进行绑定,所以可以直接从工作线程更新属性
    • 好吧,你们把我弄丢了。是否有可能提供代码链接或 sn-p 来澄清一些问题?
    【解决方案2】:

    为什么会出现这个问题?

    看起来这个循环应该需要几微秒才能完成。如果是这样,则控件是否在循环结束时重绘没有明显区别。

    如果列表那么大,你还是应该考虑分页。

    如果获取数据需要很长时间,您应该按照上面的建议在不同的线程中进行。但是,如果它那么复杂,我认为您应该真正考虑在按钮单击事件处理程序中没有复杂的逻辑,并转向更多的 MVVM 模型。

    【讨论】:

    • 好的,我会考虑使用不同的线程。这不是很复杂的逻辑,但一些迭代可能需要 10-15 秒,因为它解析一个文本文件并且列表通常是 20-30 项。
    【解决方案3】:

    感谢大家的帮助!一旦你让我指出正确的方向,我就能完全按照我的意愿工作。有了你的提示和这个链接:Worker Threads & Dispatcher 我可以用几行额外的代码来实现它。另外,我又一次学到了关于 WPF 的新知识。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-28
      • 1970-01-01
      • 2016-03-04
      • 2020-02-06
      • 2015-07-04
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多