gpt4 book ai didi

c# - ItemsControl - 可绑定(bind)集合 - 通过计时器事件更新 Ui

转载 作者:太空宇宙 更新时间:2023-11-03 14:40:34 27 4
gpt4 key购买 nike

我正在为现场的几个传感器设备创建一个仪表板类型的用户界面。基于计时器的事件从数据库中获取最后一条记录并更新仪表板 UI。我想动态创建位于 BindableCollection 上的“传感器”,然后与包含嵌套 ItemsControl 的 XAML 上的 ItemsControl 相关联。使用 MVVM 架构和 Caliburn Micro 进行绑定(bind)。

已使用完整属性并确保在更新 BindableColleciton 后调用 NotifyOfPropertyChange

编辑:在其他线程之后,我更改了 DispatcherTimer() 的 System.Timer,以便更新在 UI 线程上运行。 DispatcherTimer vs a regular Timer in WPF app for a task scheduler

此外,因为我的 BindableCollection 成员总是相同的,所以我确保每次都重新创建集合,因为我有这样的想法“ObservableCollection 将在添加或删除记录时通知 UI,但在编辑记录时不会. 由已更改的对象通知它已更改。”

属性:

  private int _offlineSensors;
public int OfflineSensors
{
get { return _offlineSensors; }
set
{
_offlineSensors = value;
NotifyOfPropertyChange(() => OfflineSensors);

}
}

private int _latchedAlarms;
public int LatchedAlarms
{
get { return _latchedAlarms; }
set
{
_latchedAlarms = value;
NotifyOfPropertyChange(() => LatchedAlarms);
}
}

private int _activeAlarms;
public int ActiveAlarms
{
get { return _activeAlarms; }
set
{
_activeAlarms = value;
NotifyOfPropertyChange(() => ActiveAlarms);

}
}

private Caliburn.Micro.BindableCollection<SensorStatusTable> _sensorStatusFilteredDash;
public Caliburn.Micro.BindableCollection<SensorStatusTable> SensorStatusFilteredDash
{
get { return _sensorStatusFilteredDash; }
set
{
_sensorStatusFilteredDash = value;
NotifyOfPropertyChange(() => SensorStatusFilteredDash);
}
}

XAML:

<ItemsControl Foreground="Black" Background="Black" ItemsSource="{Binding Path=SensorStatusFilteredDash, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="RoyalBlue" BorderThickness="2" Margin="2" Padding="5">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" FontSize="20" />
<Image MaxWidth="60" MaxHeight="60" Source="{Binding CardStatusImage, Converter={StaticResource ResourceKey = ImageConverter}, UpdateSourceTrigger=PropertyChanged}" Stretch="Uniform"></Image>
<ItemsControl Foreground="Black" Background="Black" ItemsSource="{Binding Path=SensorTypes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding }" TextWrapping="WrapWithOverflow" FontWeight="Bold" FontSize="12" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Margin="25.5,1,18,1"></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Foreground="Black" Background="Black" ItemsSource="{Binding Path=InternalSensorStatusImages, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Margin="11.5,1" MaxWidth="40" HorizontalAlignment="Center" VerticalAlignment="Center" MaxHeight="40" Source="{Binding Converter={StaticResource ResourceKey = ImageConverter}}" Stretch="Uniform"></Image>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Foreground="Black" Background="Black" ItemsSource="{Binding Path=InternalSensorStatusDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="WrapWithOverflow" FontWeight="Bold" FontSize="12" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Margin="10,1,10,1"></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

事件(已编辑):

 var conn = GlobalConfig.Connections.FirstOrDefault(c => c.GetType() == typeof(SQLConnector));
if (conn == null) return;
try
{
ActiveAlarms = conn.GetNumberActiveAlarms(0);
LatchedAlarms = conn.GetNumberActiveAlarms(2);
GasSensors = new Caliburn.Micro.BindableCollection<GasSensor>(conn.GetGasSensors());
SensorStatusDash = new Caliburn.Micro.BindableCollection<SensorStatusTable>(conn.SensorStatusDashboard());
_sensorStatusFilteredDash.Clear();
_sensorStatusFilteredDash = new Caliburn.Micro.BindableCollection<SensorStatusTable>(StatusImageConverter());
NotifyOfPropertyChange(() => SensorStatusFilteredDash);
NotifyOfPropertyChange(() => OfflineSensors);
NotifyOfPropertyChange(() => ActiveAlarms);
NotifyOfPropertyChange(() => LatchedAlarms);
}
catch (Exception ex)
{
_logger.Error(ex, "Error - Refreshing Dashboard Status");
}

这是我的应用程序的第一个 View / View 模型,上面的 UI 刷新事件一直有效,直到我聚焦另一个 View 并返回到它。计时器仍然被触发并将正确的状态置于 BindableCollection 上。此外,即使是简单 Int 的属性也不会更新。在属性 setter 上放置一个断点,我可以看到它永远不会触发它,就像 NotifyOfPropertyChange 事件不会被触发一样。有什么想法吗?

最佳答案

感谢大家的提示和帮助。

我已经成功了,有几件事导致 UI 没有刷新。

  1. 如上所述,我使用的是 System.Timer 中的计时器。我已将其替换为 DispatcherTimer,以确保事件将在与 UI 相同的线程上引发。
  2. 每个周期都重新创建可绑定(bind)集合以确保触发 PropertyChanged 事件,因为成员是常量并且只有属性被修改。
  3. 确保在切换 View 时取消订阅调度程序定时器事件,并在返回时重新订阅。

它是以上所有 3 点的组合。

关于c# - ItemsControl - 可绑定(bind)集合 - 通过计时器事件更新 Ui,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57085188/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com