简体   繁体   English

MVVM WPF ViewModel DispatcherTimer是否不更新视图?

[英]MVVM WPF ViewModel DispatcherTimer not updating view?

I have a DispatcherTimer in my ViewModel that i can see firing every interval, but the view is not being updated? 我的ViewModel中有一个DispatcherTimer,可以看到每个时间间隔触发,但是视图没有更新吗?

the feed data comes from a xml url and i am trying to refresh the form every x seconds. 提要数据来自xml网址,我正在尝试每x秒刷新一次表单。 Maybe more or less lables / differnt status 也许或多或少的标签/不同的状态

heres the code snippets: 这是代码段:

ViewModel.cs ViewModel.cs

public class Nodes
{
public string name { get; set; }
public string id { get; set; }
public string status { get; set; }
public string last { get; set; }
public int level { get; set; }
public string parent { get; set; }
}

public ObservableCollection<CI> CIs
{
get;
set;
}

DispatcherTimer LogTimer;

public void LoadCIs()
{
ObservableCollection<CI> cis = new ObservableCollection<CI>();

LogTimer = new DispatcherTimer();
LogTimer.Interval = TimeSpan.FromMilliseconds(10000);

LogTimer.Tick += (s, e) =>
{
    //pull node list
    List<Nodes> SortedList = PopulateNodes();

    foreach (Nodes Node in SortedList)
    {
        //create labels for all top level nodes
        if (Node.level == 3)
        {
            cis.Add(new CI { NodeName = Node.name, NodeStatus = Node.status });
        }
    }

    CIs = cis;

};

LogTimer.Start();

}

Model.cs Model.cs

public class CI : INotifyPropertyChanged {
  private string nodeName;
  private string nodeStatus;

    public string NodeName { 
     get { 
        return nodeName; 
     }

     set { 
        if (nodeName != value) { 
           nodeName = value; 
           RaisePropertyChanged("NodeName"); 
        } 
     } 
  }

    public string NodeStatus
    {
        get
        {
            return nodeStatus;
        }

        set
        {
            if (nodeStatus != value)
            {
                nodeStatus = value;
                RaisePropertyChanged("NodeStatus");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

  private void RaisePropertyChanged(string property) {
     if (PropertyChanged != null) {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
     } 
  } 
   } 

view.xaml view.xaml

<Grid> 
    <ItemsControl ItemsSource = "{Binding Path = CIs}">

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                <Grid>
                    <Label Content = "{Binding Path = NodeName, Mode = OneWay}" 
                        Background = "{Binding Path = NodeStatus, Mode = OneWay}" 
                        Foreground="White"
                        FontFamily="Arial Black"
                        HorizontalContentAlignment="Center"                            
                        BorderBrush="Black" 
                        BorderThickness="1,1,1,1"/>

                </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

    </ItemsControl>

</Grid>

how the form should look without timer enabled / commented out: 在不启用计时器的情况下,表单应如何显示/已注释掉:

在此处输入图片说明

with the timer code enabled nothing is added to grid: 启用计时器代码后,不会将任何内容添加到网格:

在此处输入图片说明

Thanks for looking 谢谢看

The problem: 问题:

You are changing the Collection CIs but do not notify it is changed. 您正在更改集合CIs但不通知它已更改。 ObservableCollections report their changes but you're overwriting it, it will not report that. ObservableCollections报告它们的更改,但是您正在覆盖它,它不会报告。


Option 1: 选项1:

Because you use an ObservableCollection you can add it to the bound collection directly and it will notify the UI automatically. 因为您使用的是ObservableCollection ,所以可以将其直接添加到绑定的集合中,它将自动通知UI。 So instead of: 所以代替:

cis.Add(new CI { NodeName = Node.name, NodeStatus = Node.status });

Do this: 做这个:

CIs.Add(new CI { NodeName = Node.name, NodeStatus = Node.status });

if you do this you have to initialize CIs first: 如果这样做,则必须首先初始化CIs项:

public ObservableCollection<CI> CIs
{
    get;
    set;
} = new ObservableCollection<CI>(); // < initialize it

Option 2: 选项2:

Add the INotifyPropertyChanged interface to the Nodes class and notify like this: INotifyPropertyChanged接口添加到Nodes类,并像这样进行通知:

this.PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( this.CIs ) ) );

in the setter of CIs CIs制定者中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM