【问题标题】:在datagrid wpf中同时运行多个计时器
【发布时间】:2022-01-23 11:35:02
【问题描述】:

我是 Window Presentation Foundation (WPF) 的新手。我有一个数据网格可以很好地显示数据,但我现在想在 Time 列中显示时间动态,例如每行数据每秒更改一次的调用时间。

这是我的课

 public class UserTab
{
    public int Id { get; set; }
    public string AgentName { get; set; }
    public string Extension { get; set; }
    public string Name { get; set; }
    public DateTime Birthday { get; set; }
    public string RowDetail { get; set; }
    public int ActiveParticipants { get; set; }
    public int HeldParticipants { get; set; }
    public int Duration { get; set; }
    public string CallStatus { get; set; }
    public string QueueName { get; set; }
    public string Time { get; set; }
    public string CallStatusColor { get; set; }
    public bool isRowDetail { get; set; }
    public List<UserTab> GetUsers()
    {
        List<UserTab> users = new List<UserTab>();
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:40:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "John Doe", Extension = "42033", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
        users.Add(new UserTab() { CallStatusColor = "#d70d0d", Time = "00:05:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Not Ready - Lunch", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "John Doe", Extension = "42034", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:00:30", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "John Doe", Extension = "42035", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:06:00", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "AJohn Doe", Extension = "42036", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:05:00", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "BJohn Doe", Extension = "42037", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:00:55", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "CJohn Doe", Extension = "42038", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:00:40", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "DJohn Doe", Extension = "42039", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
        users.Add(new UserTab() { CallStatusColor = "#E6A30C", Time = "00:55:00", QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "EJohn Doe", Extension = "42003", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:06:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "EJohn Doe", Extension = "42053", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:10:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "FJohn Doe", Extension = "42073", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:00:20", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "GJohn", Extension = "42078", Name = "Sammy", Birthday = new DateTime(1991, 9, 2) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:00:41", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "HJohn Doe", Extension = "42083", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:25:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "IJohn Doe", Extension = "42093", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
        users.Add(new UserTab() { CallStatusColor = "#1BDA6D", Time = "00:00:00", QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "JJohn Doe", Extension = "42013", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
       
        return users;
    }
}

  public partial class Tabs : Window
  { 
        InitializeComponent();
        List<UserTab> us = new List<UserTab>();
        UserTab user = new UserTab();
        us = user.GetUsers();
        dgSimple.ItemsSource = us
}

这里是数据网格

 <DataGrid Name="dgSimple" VerticalAlignment="Center" VerticalContentAlignment="Center" CellStyle="{StaticResource Body_Content_DataGrid_Centering}" Height="350" EnableRowVirtualization="False">
                                        <DataGrid.Columns>
                                            <DataGridTextColumn Header="Agent Name" Binding="{Binding AgentName}" IsReadOnly="True" />
                                            <DataGridTemplateColumn SortMemberPath="CallStatus" CanUserSort="True" Header="Status" CellTemplate="{StaticResource StatusTemplate}"/>
                                            <DataGridTextColumn Header="Time" Binding="{Binding Time}" IsReadOnly="True"/>
                                            <DataGridTextColumn Header="Extension" Binding="{Binding Extension}" IsReadOnly="True" />
                                        </DataGrid.Columns>
  </DataGrid>

【问题讨论】:

  • 不确定您是否遵循任何设计模式,因为您没有提供任何代码,但是每行都有自己的计时器滴答声会很愚蠢(想象一下,如果您有 10 000 行 = 10 000 个计时器滴答作响? )。可能您需要一个计时器来循环遍历每一行并更新每一行的时间(如果您使用 mvvm 设计模式,请查看模型/模型)
  • 我没有使用任何设计模式。你能提供一些代码实现吗
  • 这个专栏的多重绑定怎么样?一个绑定到您的视图模型值,另一个绑定到驱动它的任何差异。每秒改变这种差异。使用多转换器计算您想要在单元格中显示的内容。它确实取决于您拥有多少行数据。您可以有一个计时器并每秒迭代一次所有行视图模型。如果您有数百个这些行,那应该没问题。看起来像呼叫中心数据给我。这不太可能意味着成千上万的代理。

标签: c# wpf timer datagrid


【解决方案1】:

一个基于您的代码的简单示例,它每 1 秒刷新一次 DataGrid

  1. Tabs 类中,通过StartMockValue 启动一个新线程来模拟Time 值。

  2. StartRefreshDataGrid中,启动一个新线程来判断是否更新DataGrid

  3. 如果TimeDisplayTime 不同,则设置UserTab -&gt; DisplayTime 以通知属性已更改。

  4. 最后,DataGrid 被新数据更新了。

Tabs.xaml

<Window x:Class="TestWpfApp.Tabs"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
    <StackPanel>
         <DataGrid Name="dgSimple" VerticalAlignment="Center" VerticalContentAlignment="Center" Height="350"
                   EnableRowVirtualization="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Agent Name" Binding="{Binding AgentName}" IsReadOnly="True" />
                <DataGridTemplateColumn SortMemberPath="CallStatus" CanUserSort="True" Header="Status"/>
                <!--NOTE: bind 'DisplayTime' instead of 'Time'-->
                <DataGridTextColumn Header="Time" Binding="{Binding DisplayTimeString}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Extension" Binding="{Binding Extension}" IsReadOnly="True" />
            </DataGrid.Columns>
         </DataGrid>
    </StackPanel>
</Window>

Tabs.xaml.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace TestWpfApp
{
    public partial class Tabs : Window
    {
        public Tabs()
        {
            InitializeComponent();

            this.Users = new List<UserTab>();
            UserTab user = new UserTab();
            this.Users = user.GetUsers();
            dgSimple.ItemsSource = this.Users;

            this.StartMockValue(); 

            this.StartRefreshDataGrid();
        }

        private List<UserTab> Users;

        private void StartMockValue()
        {
            // NOTE: this is a thread to mock the business logic, it change 'Time' value.
            Task.Run(() =>
            {
                var rando = new Random();
                while (true)
                {
                    foreach (var user in this.Users)
                    {
                        if (rando.Next(0, 3) == 1)
                        {
                            user.Time = user.Time + 1;
                        }
                    }

                    Thread.Sleep(1000);
                }
            });
        }

        public void StartRefreshDataGrid()
        {
            // NOTE: this is a thread to update data grid.
            Task.Run(() =>
            {
                while (true)
                {
                    foreach (var user in this.Users)
                    {
                        // NOTE: update if the time changed.
                        if (user.DisplayTime != user.Time)
                        {
                            user.DisplayTime = user.Time;
                        }
                    }

                    // NOTE: refresh the grid every seconds.
                    Thread.Sleep(1000);
                }
            });
        }
    }
}

UserTab.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace TestWpfApp
{
    public class UserTab : INotifyPropertyChanged
    {
        public int Id { get; set; }
        public string AgentName { get; set; }
        public string Extension { get; set; }
        public string Name { get; set; }
        public DateTime Birthday { get; set; }
        public string RowDetail { get; set; }
        public int ActiveParticipants { get; set; }
        public int HeldParticipants { get; set; }
        public int Duration { get; set; }
        public string CallStatus { get; set; }
        public string QueueName { get; set; }

        // NOTE: this is the 'real time', some business thread will update the value.
        public int Time { get; set; }

        private int displayTime;

        // NOTE: this is the 'displayed time' in the DataGrid.
        public int DisplayTime
        {
            get => displayTime;
            set
            {
                displayTime = value;
                this.OnPropertyChange(nameof(this.DisplayTimeString));
            }
        }

        public string DisplayTimeString => $"{displayTime / 60 / 60}:{displayTime / 60 % 60}:{displayTime % 60}";

        public string CallStatusColor { get; set; }
        public bool isRowDetail { get; set; }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChange(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public List<UserTab> GetUsers()
        {
            var maxSeconds = 24 * 60 * 60;
            var random = new Random();


            List<UserTab> users = new List<UserTab>();
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "John Doe", Extension = "42033", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new UserTab() { CallStatusColor = "#d70d0d", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Not Ready - Lunch", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "John Doe", Extension = "42034", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "John Doe", Extension = "42035", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "AJohn Doe", Extension = "42036", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "BJohn Doe", Extension = "42037", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "CJohn Doe", Extension = "42038", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "DJohn Doe", Extension = "42039", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
            users.Add(new UserTab() { CallStatusColor = "#E6A30C", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = true, CallStatus = "Talking", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "EJohn Doe", Extension = "42003", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "EJohn Doe", Extension = "42053", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "FJohn Doe", Extension = "42073", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "GJohn", Extension = "42078", Name = "Sammy", Birthday = new DateTime(1991, 9, 2) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 1, AgentName = "HJohn Doe", Extension = "42083", Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 2, AgentName = "IJohn Doe", Extension = "42093", Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
            users.Add(new UserTab() { CallStatusColor = "#1BDA6D", DisplayTime = random.Next(0, maxSeconds), QueueName = "AMQ", isRowDetail = false, CallStatus = "Ready", Duration = 1000, HeldParticipants = 500, ActiveParticipants = 30, Id = 3, AgentName = "JJohn Doe", Extension = "42013", Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });
            return users;
        }
    }
}

【讨论】:

  • 感谢您的回答。如果我不想每秒更新整个网格怎么办。我只想更新特定列,例如我的情况“时间”
  • 您的意思是您只想更新更改的行吗?比较real value和DataGriddisplay value,如果值发生变化,那么更新字段Time就可以了~
  • 我更新了答案,它只刷新值已更改的单元格。
  • 正如您在参考 Datagrid Image Time Column 值时看到的那样。我只想在将数据绑定到网格后增加一秒而不更新用户列表中的值。作为参考social.msdn.microsoft.com/Forums/onedrive/en-US/…
  • 我的建议是写两个模型,把业务逻辑和视图分开,用ViewModel更新View。参考这里:en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 1970-01-01
  • 2017-03-17
  • 2012-10-06
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多