使用INotifyPropertyChanged进行WPF UI更新

时间:2013-11-18 21:09:59

标签: c# wpf inotifypropertychanged

感谢您的时间。我有一个WPF这样的问题...它更新UI,只有当方法(由按钮点击触发)到达结束时才更新它。但是,在我的真实应用程序中,我需要立即更新UI以查看信息。

我试着阅读教程和帖子,我准备放弃....我会很感激任何想法为什么会发生和做什么: - )。

我有一个标准的xaml:带有文本框和按钮:

<TextBox Text="{Binding FirstName}"/>
<Button Content="Run" Click="Button_Click" />

在它后面

 public partial class MainWindow
    {
        public Person Person = new Person();

        public MainWindow()
        {
            InitializeComponent();
            DataContext = Person;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Person.FirstName = "John";
            Thread.Sleep(10000);
///// Only Here I can see the update.
        }
    }

DataContext是:

    public class Person:INotifyPropertyChanged
    {
       private string _FirstName;

        public string FirstName
        {
            get { return _FirstName; }
            set
            {
                if (_FirstName == value)
                    return;
                _FirstName = value;
                OnPropertyChanged("FirstName");

            }
        }
....

标准OnProertyChanged实施。

2 个答案:

答案 0 :(得分:2)

您永远不应使用Sleep阻止UI线程。相反,您可能希望将该部分代码放在后台线程上。例如,使用Task.Factory.StartNew:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Person.FirstName = "John";
    Task.Factory.StartNew( () => {
        Thread.Sleep(10000);

        // ...
    });
}

请注意,您无法在该线程内进行任何其他UI更改。如果需要,请使用Dispatcher.BeginInvoke将其发送回UI线程。

例如,根据评论:

Person.FirstName = "John";
Task.Factory.StartNew( () => {
    foreach (string mlsNumber in ourMlses) 
    { 
        Listing listing = sourceSite.ParseByMls(mlsNumber); 
        if (listing != null) 
        { 
            var successDb = sourceSite.UpdateListing(listing); 
            if (!successDb) 
            { 
                throw new Exception("Db error"); 
            } 

            Dispatcher.BeginInvoke( () => {

                // UI update that listing have been added to the DB 
            });
        }
    }
} );

答案 1 :(得分:0)

我假设您在Button_Click方法中运行了一个冗长的操作,并希望首先使用新的 FirstName 更新UI。尝试用Dispatcher.Invoke方法结束 FirstName 初始化:

 private void Button_Click(object sender, RoutedEventArgs e)
 {
      Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, 
            new Action(() => {
                Person.FirstName = "John";
            }));
      // Run a lengthy operation here
 }

它将以与退出Button_Click方法后相同的方式触发PropertyChanged事件的UI更新。

P.S。但是,你在这里看到的所有代码都是非常糟糕的做法,我会谋杀一个编写它的开发人员。但它可能适合某些学术目的。要做出正确的解决方案,最好使用Commands并在 ViewModel 中处理它,而不是点击处理程序。