C# 为什么AsyncTaskManager中的PropertyChanged始终为空?
我尝试实现与本文中介绍的模式类似的东西: 以下是我的问题描述: 我认为:C# 为什么AsyncTaskManager中的PropertyChanged始终为空?,c#,.net,mvvm,async-await,C#,.net,Mvvm,Async Await,我尝试实现与本文中介绍的模式类似的东西: 以下是我的问题描述: 我认为: <Button Content="LoadData" Command="{Binding LoadDataCommand}" /> <ListBox Grid.Row="1" x:Name="listBox" ItemsSource="{Binding DataSource.Result}" 然后在ProductViewModel中: public AsyncTaskManager<Observ
<Button Content="LoadData" Command="{Binding LoadDataCommand}" />
<ListBox Grid.Row="1" x:Name="listBox" ItemsSource="{Binding DataSource.Result}"
然后在ProductViewModel中:
public AsyncTaskManager<ObservableCollection<Product>> DataSource { get; private set; }
}请尝试创建一组最小的可复制代码,并观察调试器中的输出窗口中的数据绑定错误 以下代码对我来说很好(在LINQPad中):
void Main()
{
var context=new ParserContext();
context.xmlnsdirectionary.Add(“,”http://schemas.microsoft.com/winfx/2006/xaml/presentation");
var xaml=@”;
var element=(FrameworkElement)XamlReader.Parse(xaml,context);
element.DataContext=新产品视图模型();
PanelManager.StackwFelement(元素);
}
类ProductViewModel
{
公共产品视图模型()
{
DataSource=新的AsyncTaskManager(LoadProductsAsync());
}
专用异步任务LoadProductsAsync()
{
等待任务。延迟(10000);
返回新的observeCollection{“first”、“second”、“third”};
}
公共AsyncTaskManager数据源{get;private set;}
}
列表框首先显示为空,然后在延迟后填充值。因为它很可能是在设置绑定之前完成的。好了,现在我知道问题到底出在哪里了。当我在ProductViewModel构造函数中设置DataSource时,一切都正常,但当我在LoadDataAction中设置此项时(loadDataCommand绑定到“load data”按钮),则AsyncTaskManager PropertyChanged为空。我编辑了我的问题,我不明白为什么会这样:(您需要为视图模型中更改的每个属性提升
PropertyChanged
。在这种情况下,ProductViewModel.DataSource
属性中缺少该属性。好了,现在它可以工作了,我在构造函数中设置DataSource时不必提升PropertyChanged。在构造函数中设置它时,它永远不会更改。)s、 因此不需要PropertyChanged
。如果构建viewmodel然后更改属性值,则需要提高PropertyChanged
。
public AsyncTaskManager<ObservableCollection<Product>> DataSource { get; private set; }
public ProductViewModel()
{
_loadDataCommand = new DelegateCommand(LoadDataAction);
}
private void LoadDataAction(object p)
{
ProductRepository pRepository = new ProductRepository();
DataSource = new AsyncTaskManager<ObservableCollection<Product>>(pRepository.LoadProducts());
}
ProductRepository pRepository = new ProductRepository();
DataSource = new AsyncTaskManager<ObservableCollection<Product>>(pRepository.LoadProducts());
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;
}
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; }
}