从 DispatcherTimer.Tick 添加时,C# ListBox 不显示添加的项目
C# ListBox not showing added items when added from DispatcherTimer.Tick
这对我来说似乎是一种奇怪的行为,因为我不想责怪除我自己以外的任何人,所以我花了几个小时试图解决这个问题 - 但我根本不明白这一点:
我刚刚注意到问题出现在 DispatcherTimer.Tick 事件调用的方法中。这可能是一个多线程问题。
我有一个列表框:
<ListBox ItemsSource="{Binding ConfigurationErrors, Mode=OneWay}"/>
它绑定到:
private ObservableCollection<string> _configurationErrors = new ObservableCollection<string>();
public ObservableCollection<string> ConfigurationErrors {
get {
return _configurationErrors;
}
}
/// <summary>
/// Adds a configuration error to the window.
/// </summary>
/// <param name="ErrorMessage">The message to add.</param>
public void AddConfigurationError(string ErrorMessage) {
if(String.IsNullOrEmpty(ErrorMessage))
return;
_configurationErrors.Add(ErrorMessage);
NotifyPropertyChanged("ConfigurationErrors");
}
/// <summary>
/// Removes all configuration errors from the window.
/// </summary>
public void ClearConfigurationErrors() {
_configurationErrors.Clear();
NotifyPropertyChanged("ConfigurationErrors");
}
AddConfigurationError(string ErrorMessage)
调用成功添加消息
来自我 MainWindow
中的任何地方。
(来自构造函数和其他任何地方)
而且我还有一个不断循环的方法(调用
DispatcherTimer.Tick) 在我的 App.cs
中存储的实例中
包含以下代码:
//File exists
if (configFilePath == null) {
_mainWindow.AddConfigurationError("Could not retrieve the config filepath.");
throw new InvalidDataException("Could not retrieve the config filepath.");
} else if (!File.Exists(configFilePath)) {
_mainWindow.AddConfigurationError("Could not find the config. (" + configFilePath + ")");
throw new InvalidDataException("Could not find the config. (" + configFilePath + ")");
}
正在抛出异常并正在调用 AddConfigurationError()
。我还可以记录传递给 AddConfigurationError()
的消息,它确实有效,但是 - 我的控件没有收到绑定更新。
这是因为 DispatcherTimer.Tick 在不同的线程中运行并且绑定可能无法按我编写的方式正常工作吗?我该如何解决?
提前谢谢你。
您无法从另一个线程访问 UI 层,您需要这样做
yourList.Invoke((MethodInvoker)(() =>
{
//add new items here
}));
除了"yourList"你还可以在主线程
上使用你的主窗体或其他东西运行
这对我有用。我使用 MVVM,但我认为它应该可以从后面的代码中工作
public MainViewModel()
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(3);
timer.Tick +=timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
AddConfigurationError("err");
}
XAML代码
<ListBox ItemsSource="{Binding ConfigurationErrors}">
</ListBox>
在适当的 MainWindow 实例上调用方法。您没有展示如何创建 _mainWindow
,而是调用
_mainWindow.AddConfigurationError(...);
你应该打电话给
((MainWindow)Application.Current.MainWindow).AddConfigurationError(...);
这对我来说似乎是一种奇怪的行为,因为我不想责怪除我自己以外的任何人,所以我花了几个小时试图解决这个问题 - 但我根本不明白这一点:
我刚刚注意到问题出现在 DispatcherTimer.Tick 事件调用的方法中。这可能是一个多线程问题。
我有一个列表框:
<ListBox ItemsSource="{Binding ConfigurationErrors, Mode=OneWay}"/>
它绑定到:
private ObservableCollection<string> _configurationErrors = new ObservableCollection<string>(); public ObservableCollection<string> ConfigurationErrors { get { return _configurationErrors; } } /// <summary> /// Adds a configuration error to the window. /// </summary> /// <param name="ErrorMessage">The message to add.</param> public void AddConfigurationError(string ErrorMessage) { if(String.IsNullOrEmpty(ErrorMessage)) return; _configurationErrors.Add(ErrorMessage); NotifyPropertyChanged("ConfigurationErrors"); } /// <summary> /// Removes all configuration errors from the window. /// </summary> public void ClearConfigurationErrors() { _configurationErrors.Clear(); NotifyPropertyChanged("ConfigurationErrors"); }
AddConfigurationError(string ErrorMessage)
调用成功添加消息
来自我 MainWindow
中的任何地方。
(来自构造函数和其他任何地方)
而且我还有一个不断循环的方法(调用 DispatcherTimer.Tick) 在我的
App.cs
中存储的实例中 包含以下代码://File exists if (configFilePath == null) { _mainWindow.AddConfigurationError("Could not retrieve the config filepath."); throw new InvalidDataException("Could not retrieve the config filepath."); } else if (!File.Exists(configFilePath)) { _mainWindow.AddConfigurationError("Could not find the config. (" + configFilePath + ")"); throw new InvalidDataException("Could not find the config. (" + configFilePath + ")"); }
正在抛出异常并正在调用 AddConfigurationError()
。我还可以记录传递给 AddConfigurationError()
的消息,它确实有效,但是 - 我的控件没有收到绑定更新。
这是因为 DispatcherTimer.Tick 在不同的线程中运行并且绑定可能无法按我编写的方式正常工作吗?我该如何解决?
提前谢谢你。
您无法从另一个线程访问 UI 层,您需要这样做
yourList.Invoke((MethodInvoker)(() =>
{
//add new items here
}));
除了"yourList"你还可以在主线程
上使用你的主窗体或其他东西运行这对我有用。我使用 MVVM,但我认为它应该可以从后面的代码中工作
public MainViewModel()
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(3);
timer.Tick +=timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
AddConfigurationError("err");
}
XAML代码
<ListBox ItemsSource="{Binding ConfigurationErrors}">
</ListBox>
在适当的 MainWindow 实例上调用方法。您没有展示如何创建 _mainWindow
,而是调用
_mainWindow.AddConfigurationError(...);
你应该打电话给
((MainWindow)Application.Current.MainWindow).AddConfigurationError(...);