[英]Binding arrays in WPF
I have a problem with binding data in WPF. 我在WPF中绑定数据时遇到问题。 Task runed in constructor work perfect.
在构造函数中运行的任务工作完美。 But when i tried to run task in timer handler it didnt work -> the data in view didnt update...
但是当我尝试在计时器处理程序中运行任务时它没有起作用->视图中的数据没有更新...
public ObservableCollection<ushort> Test2{get; set;}
public Settings()
{
InitializeComponent();
Test2 = new ObservableCollection<ushort>();
Test2.Add(666);
Test2.Add(111);
Task.Run(async () =>
{
int i = 0;
while (true)
{
await Task.Delay(500);
Test2[1] += (ushort)2;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test2)));
}
});
}
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Task.Run(async () =>
{
int i = 0;
while (true)
{
await Task.Delay(500);
Test2[1] += (ushort)2;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test2)));
}
});
}
Timer 计时器
oTimer.Interval = 1000;
oTimer.Elapsed += OnTimedEvent;
oTimer.AutoReset = true;
oTimer.Enabled = true;
oTimer.Start();
Other class file 其他班级文件
public UserControlHome()
{
InitializeComponent();
DataContext = new Settings();
}
And the XML file 和XML文件
<TextBlock x:Name="Tob2Sensor1" Grid.Column="1" Text="{Binding Test2[1]}" HorizontalAlignment="Center"/>
Try removing the task from the timer event: 尝试从计时器事件中删除任务:
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Test2[1] += (ushort)2;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test)));
}
Try wrap it up inside a Dispatcher 尝试将其包装在分派器中
Application.Current.Dispatcher.Invoke(() => PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test)));));
EDIT: This works for me (I'm using latest Prism.Core from Nuget): 编辑:这对我有效(我正在使用Nuget的最新Prism.Core):
using Prism.Mvvm;
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
namespace ArrayBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Settings();
}
}
class Settings: BindableBase
{
public ObservableCollection<ushort> Test2 { get; set; }
private Timer oTimer = new Timer();
public Settings()
{
Test2 = new ObservableCollection<ushort>();
Test2.Add(666);
Test2.Add(111);
oTimer.Interval = 1000;
oTimer.Elapsed += OnTimedEvent;
oTimer.AutoReset = true;
oTimer.Enabled = true;
oTimer.Start();
}
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Task.Run(async () =>
{
while (true)
{
await Task.Delay(500);
Test2[1] += (ushort)2;
}
});
}
}
}
In the constructor version you don't need to call PropertyChanged
- which is why it works 在构造函数版本中,您无需调用
PropertyChanged
这就是它起作用的原因
In the timer callback version, your PropertyChanged
line is incorrect, try this: 在计时器回调版本中,您的
PropertyChanged
行不正确,请尝试以下操作:
PropertyChanged(this, new PropertyChangedEventArgs("Test2[1]"));
Might be a cross-threading problem. 可能是跨线程问题。 WPF does not allow changing bound collection from outside the UI thread.
WPF不允许从UI线程外部更改绑定集合。 Try the following:
请尝试以下操作:
<!-- language: c# -->
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Task.Run(async () =>
{
int i = 0;
while (true)
{
await Task.Delay(500);
Dispatcher.Invoke(()=>
{
Test2[1] += (ushort)2;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test2)));
});
}
}
}
IMO the 'async' part is obsolete. IMO的“异步”部分已过时。 You can do as Nick has written, but inside the dispatcher invoke.
您可以像Nick所写的那样做,但是在调度程序内部调用。
Ok, i made few changes. 好的,我做了几处更改。
public Settings()
{
InitializeComponent();
Test2 = new ObservableCollection<ushort>();
Test2.Add(100);
Test2.Add(99);
Test2.Add(98);
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Task.Run(async () =>
{
int i = 0;
while (true)
{
await Task.Delay(500);
Dispatcher.Invoke(() =>
{
Test2[1] += (ushort)2;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Test2)));
});
}
});
}
public void Button_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Start();
}
And it doesnt work. 而且它不起作用。 But when I run timer "dispatcherTimer.Start();"
但是当我运行计时器“ dispatcherTimer.Start();”时 in constructor everythink is ok....
在构造函数中,一切都可以。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.