我一直在努力学习并利用WPF和数据绑定。我有一个列表视图,其中的列将显示三个图像中的一个,如此片段所示:
<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));
}
}
我在listview窗口页面上有一个按钮:
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循环的每次迭代都会更新相应行的图像。毫无疑问,我错过了关于这一切如何运作的重要事项。有什么提示吗?
答案 0 :(得分:4)
我遇到的问题是,在foreach循环完成并且btnStart_Click()方法完成之后,图像才会更新。一旦发生这种情况,所有图像都会按预期更新,而不是一次性更新。
我想要的,以及我认为会发生的事情是,foreach循环的每次迭代都会更新相应行的图像。毫无疑问,我错过了关于这一切如何运作的重要事项。有什么提示吗?
这是你如何更新的问题。
问题不在于UI没有更新 - 在内部,它确实如此。问题是你在主UI线程上进行了这个更新,以及你的foreach循环。执行此操作时,UI将被完全阻止(而不是刷新/重绘),直到您的操作完成100%,并且消息泵可以再次运行。
有一些选项可以解决这个问题 - 如果你的操作需要一段时间,并且你希望它在运行时更新,你可以将foreach循环移动到在后台线程上运行的委托中。然后,您将使用Dispatcher将状态更新重新调用回UI线程。
当你有一个长时间运行的操作时,这有几个好处:
答案 1 :(得分:0)
为什么这是一个问题?
看起来这个循环应该花费几微秒才能完成。如果是这样,那么控件是否在循环结束时重绘是没有明显区别的。
如果列表很大,你应该考虑分页。
如果获取数据需要很长时间,您应该在另一个线程中执行此操作,如上所述。但是,如果它很复杂,我认为你应该真正关注按钮点击事件处理程序中没有复杂的逻辑,并转向更多的MVVM模型。
答案 2 :(得分:0)
感谢所有的帮助!一旦你让我指向了正确的方向,我就能够像我想的那样工作。通过你的提示和这个链接:Worker Threads & Dispatcher我能够通过一些额外的代码来实现它。另外,我再次学到了一些关于WPF的新内容。