2014-04-15 79 views
0

我嘗試實施某物類似於本文中介紹的模式: http://msdn.microsoft.com/en-us/magazine/dn605875.aspx爲什麼在AsyncTaskManager PropertyChanged始終爲空?

下面是我的問題描述:

在我看來,我已設置:

<Button Content="LoadData" Command="{Binding LoadDataCommand}" /> 
<ListBox Grid.Row="1" x:Name="listBox" ItemsSource="{Binding DataSource.Result}" 
在代碼隱藏

然後:

this.DataContext = new ProductViewModel(); 

然後在ProductViewModel中:

public AsyncTaskManager<ObservableCollection<Product>> DataSource { get; private set; } 

AND:

public ProductViewModel() 
    { 
     _loadDataCommand = new DelegateCommand(LoadDataAction); 

    } 
private void LoadDataAction(object p) 
    { 
     ProductRepository pRepository = new ProductRepository(); 
     DataSource = new AsyncTaskManager<ObservableCollection<Product>>(pRepository.LoadProducts());  
    } 

並在AsyncTaskManager的PropertyChanged總是空:(這是爲什麼?綁定有什麼問題?

但是當我刪除「加載數據」按鈕,_loadDataCommand,只是簡單地設置

ProductRepository pRepository = new ProductRepository(); 
     DataSource = new AsyncTaskManager<ObservableCollection<Product>>(pRepository.LoadProducts()); 
ProductViewModel構造

那麼它像在例如工作,但我希望用戶有可能使用調用加載數據按鈕不是在構造函數中啓動:/

下面是AsyncTaskManager代碼:

using System; 
using System.ComponentModel; 
using System.Threading.Tasks; 

namespace PhoneClientApp.Models 
{ 
    public sealed class AsyncTaskManager<TResult> : INotifyPropertyChanged 
    { 
    public AsyncTaskManager(Task<TResult> task) 
    { 
     Task = task; 
     if (!task.IsCompleted) 
     { 
      var _ = WatchTaskAsync(task); 
     } 
    } 

    private async Task WatchTaskAsync(Task task) 
    { 
     try 
     { 
      await task; 
     } 
     catch 
     { 
     } 
     var propertyChanged = PropertyChanged; 
     if (propertyChanged == null) 
      return; 
     propertyChanged(this, new PropertyChangedEventArgs("Status")); 
     propertyChanged(this, new PropertyChangedEventArgs("IsCompleted")); 
     propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted")); 
     if (task.IsCanceled) 
     { 
      propertyChanged(this, new PropertyChangedEventArgs("IsCanceled")); 
     } 
     else if (task.IsFaulted) 
     { 
      propertyChanged(this, new PropertyChangedEventArgs("IsFaulted")); 
      propertyChanged(this, new PropertyChangedEventArgs("Exception")); 
      propertyChanged(this, 
       new PropertyChangedEventArgs("InnerException")); 
      propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage")); 
     } 
     else 
     { 
      propertyChanged(this, 
       new PropertyChangedEventArgs("IsSuccessfullyCompleted")); 
      propertyChanged(this, new PropertyChangedEventArgs("Result")); 
     } 
    } 

    public Task<TResult> Task { get; private set; } 

    public TResult Result 
    { 
     get 
     { 
      return (Task.Status == TaskStatus.RanToCompletion) 
       ? Task.Result 
       : default(TResult); 
     } 
    } 

    public TaskStatus Status 
    { 
     get { return Task.Status; } 
    } 

    public bool IsCompleted 
    { 
     get { return Task.IsCompleted; } 
    } 

    public bool IsNotCompleted 
    { 
     get { return !Task.IsCompleted; } 
    } 

    public bool IsSuccessfullyCompleted 
    { 
     get 
     { 
      return Task.Status == 
        TaskStatus.RanToCompletion; 
     } 
    } 

    public bool IsCanceled 
    { 
     get { return Task.IsCanceled; } 
    } 

    public bool IsFaulted 
    { 
     get { return Task.IsFaulted; } 
    } 

    public AggregateException Exception 
    { 
     get { return Task.Exception; } 
    } 

    public Exception InnerException 
    { 
     get 
     { 
      return (Exception == null) 
       ? null 
       : Exception.InnerException; 
     } 
    } 

    public string ErrorMessage 
    { 
     get 
     { 
      return (InnerException == null) 
       ? null 
       : InnerException.Message; 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

}

+0

因爲它在綁定被設置之前就完成了,所以很有可能。 – Will

回答

2

請嘗試創建最小可重現的代碼集,並在調試器中觀察輸出窗口中的數據綁定錯誤。

下面的代碼工作得很好,我(在LINQPad):

void Main() 
{ 
    var context = new ParserContext(); 
    context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"); 
    var xaml = @"<Grid><ListBox ItemsSource=""{Binding DataSource.Result}"" /></Grid>"; 
    var element = (FrameworkElement)XamlReader.Parse(xaml, context); 
    element.DataContext = new ProductViewModel(); 

    PanelManager.StackWpfElement(element); 
} 

class ProductViewModel 
{ 
    public ProductViewModel() 
    { 
     DataSource = new AsyncTaskManager<ObservableCollection<string>>(LoadProductsAsync()); 
    } 

    private async Task<ObservableCollection<string>> LoadProductsAsync() 
    { 
     await Task.Delay(10000); 
     return new ObservableCollection<string> { "first", "second", "third" }; 
    } 

    public AsyncTaskManager<ObservableCollection<string>> DataSource { get; private set; } 
} 

列表框首先顯示爲空,然後經過延遲填充值。

+0

現在好了,我看到問題到底在哪裏。當我在ProductViewModel構造函數中設置DataSource時,一切正常,但是當我在LoadDataAction中設置_loadDataCommand綁定到按鈕「加載數據」時,則AsyncTaskManager PropertyChanged爲null。我編輯了我的問題,我不明白爲什麼它是這樣的:( – Snorlax

+1

你需要提高'PropertyChanged' *視​​圖模型中每個改變*的屬性。在這種情況下,你錯過了'ProductViewModel.DataSource 'property。 –

+0

現在好了,它可以工作,當我在構造函數中設置DataSource時,我不需要提高PropertyChanged – Snorlax

相關問題