WPF绑定到TextBlock不会立即更新目标

时间:2011-05-10 14:13:19

标签: wpf binding

我认为我的问题不属于其他任何人,所以希望有人可以帮助我。

我使用INotifyPropertyChnaged设置了TextBlock绑定,它确实有效。我遇到的问题是它何时更新目标控件(TextBlock)

快速查看我的代码

namespace XYZ
{
    public partial class Loading : Window
    {
        StatusMessage msg = StatusMessage.GetInstance();

        public loading()
        {
            InitializeComponent();
            this.DataContext = msg;
        }

        private void LoadBackEndUsers()
        {

            msg.Status = "Loading Users";

            //txtStatus.GetBindingExpression(TextBlock.TextProperty).UpdateTarget();
            //lblLoading.Focus();
            this.txtStatus.DataContext = msg;

            beUsers = new BackendUsers(Database);
            allBEUsers = beUsers.GetAllUsers();
        }

        private void LoadProducts()
        {
            msg.Status = "Loading Products";

            //txtStatus.GetBindingExpression(TextBlock.TextProperty).UpdateTarget();
            //lblLoading.Focus();
            this.txtStatus.DataContext = msg;

            products = new Product(Database);
            allProducts = products.GetAllProducts();
         }

         private void Window_ContentRendered(object sender, EventArgs e)
         {           
             LoadBackEndUsers();          
             LoadProducts();
         }
    }
}

现在我的问题是,只有在LoadProducts()方法完成后,我的文本块才会显示“正在加载产品”。它根本不显示“正在加载用户”,因此目标只在一切完成后才更新。

如何让它立即更新。注释掉的是我只是尝试各种各样的东西来试图强制更新。

非常感谢任何帮助。

亲切的问候,

尼尔

2 个答案:

答案 0 :(得分:3)

问题是您的数据检索发生在与UI逻辑相同的线程上。这意味着即使您更改属性值并引发OnPropertyChanged,也不会在阻塞数据访问完成之后重新评估它。相反,您应该使用BackgroundWorker。这是一篇很棒的文章,介绍了如何使用它:

http://elegantcode.com/2009/07/03/wpf-multithreading-using-the-backgroundworker-and-reporting-the-progress-to-the-ui/

答案 1 :(得分:2)

您的StatusMessage课程应实施INotifyPropertyChanged

修改:我非常确定您的Window_ContentRendered事件管理器会阻止每次更新UI。我写了一个适合我的小样本:

public partial class MainWindow : Window
{
  StatusMessage msg = new StatusMessage();
  public MainWindow()
  {
    InitializeComponent();
    this.DataContext = msg;
  }

  private void LoadBackEndUsers()
  {
    Task.Factory.StartNew(() =>
      {
        this.Dispatcher.BeginInvoke(new ThreadStart(() => msg.Status = "Loading Users"), DispatcherPriority.Normal);
        //Load users here:
        Thread.Sleep(2000);
        this.Dispatcher.BeginInvoke(new ThreadStart(() => msg.Status = "Users loaded"), DispatcherPriority.Normal);

        // If users loaded start load products:
        LoadProducts();
      });
  }

  private void LoadProducts()
  {
    Task.Factory.StartNew(() =>
    {
      this.Dispatcher.BeginInvoke(new ThreadStart(() => msg.Status = "Loading Products"), DispatcherPriority.Normal);
      //Load products here:
      Thread.Sleep(2000);
      this.Dispatcher.BeginInvoke(new ThreadStart(() => msg.Status = "Products Loaded"), DispatcherPriority.Normal);
    });
  }

  private void Window_ContentRendered(object sender, EventArgs e)
  {
    LoadBackEndUsers();
    //LoadProducts();
  }
}