【问题标题】:C# ListBox not showing added items when added from DispatcherTimer.Tick从 DispatcherTimer.Tick 添加时,C# ListBox 不显示添加的项目
【发布时间】:2015-06-04 07:05:41
【问题描述】:

这对我来说似乎是一种奇怪的行为,因为我不喜欢责怪自己以外的任何人,所以我花了几个小时试图解决这个问题 - 但我根本不明白这一点:p>

我刚刚注意到问题发生在由 DispatcherTimer.Tick 事件调用的方法中。这可能是一个多线程问题。

  1. 我有一个列表框:

    <ListBox ItemsSource="{Binding ConfigurationErrors, Mode=OneWay}"/>
    
  2. 它绑定到:

    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 中的任何位置
调用该消息,则会成功添加一条消息。
(从构造函数和其他任何地方)

  1. 而且我还有一个不断循环的方法(由 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 在不同的线程中运行并且绑定可能无法按我编写的方式工作吗?我该如何解决?

提前谢谢你。

【问题讨论】:

  • 从您在此处显示的内容很难判断为什么它不起作用。至少,您既不需要双向绑定 ItemsSource,也不需要从 Add 和 Clear 方法调用 NotifyPropertyChanged。该属性本身不会改变,只会改变它包含的元素,并且已经由 ObservableCollection 类通知。
  • 您可能在另一个 MainWindow 实例上调用 AddConfigurationError 吗?
  • @Clemens 什么鬼?你说的对。在 Tick 事件中调用 Hide() 或更改 _mainWindow 的状态对我的窗口没有影响。怎么可能是另一个例子。我(应该)只有一个。我会跟随那个领导......

标签: c# wpf binding timer listbox


【解决方案1】:

在正确的 MainWindow 实例上调用方法。你还没有展示你是如何创建_mainWindow,而不是调用

_mainWindow.AddConfigurationError(...);

你应该打电话

((MainWindow)Application.Current.MainWindow).AddConfigurationError(...);

【讨论】:

  • 现在是可笑的。我没有删除 App.xaml 中的默认启动对象,即 MainWindow。那变成了窗口,显示给用户。然后我在 App() 中创建了第二个 mainWindow,调用了 AddConfigurationError()。显然,这并没有太大的影响。 +1 用于显示 Application.Current.MainWindow - 以前不知道!
【解决方案2】:

这对我有用。我使用 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>

【讨论】:

  • 这基本上就是我所做的。刚刚在错误的实例上调用了 AddConfigurationError。
【解决方案3】:

你不能从另一个线程访问 UI 层,你需要做这样的事情

yourList.Invoke((MethodInvoker)(() =>
{
    //add new items here
}));

除了“yourList”,你还可以使用你的主窗体或在主线程上运行的东西

【讨论】:

  • DispatcherTimer.Tick 已在 UI 线程中调用。这里不需要 Invoke,你显示的是 WinForms 代码,而不是 WPF。
  • 是的,Invoke() 不是窗口或列表框中的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 2021-09-27
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多