我有问题。我创建了以下ViewModel:
public class TemplateListViewModel
{
public double WidthHeight { get; set; }
public ICommand LoadTemplates => new Command(MyHandler);
public int CurrentTemplateCountReceived;
public bool HitBottomOfList = false;
public ObservableCollection<TemplateSource> sourceList { get; set; }
public TemplateListViewModel()
{
CurrentTemplateCountReceived = 0;
sourceList = new ObservableCollection<TemplateSource>();
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
var width = mainDisplayInfo.Width;
var density = mainDisplayInfo.Density;
var ScaledWidth = width / density;
WidthHeight = (ScaledWidth / 2);
loadingTemplates += onLoadingTemplates;
LoadTemplateList();
}
private event EventHandler loadingTemplates = delegate { };
private Task LoadTemplateList()
{
loadingTemplates(this, EventArgs.Empty);
return null;
}
private async void onLoadingTemplates(object sender, EventArgs args)
{
if (HitBottomOfList == false)
{
List<Template> templateList = await App.RestService.GetTemplates(App.User, CurrentTemplateCountReceived);
if (templateList != null)
{
foreach (var template in templateList)
{
ImageSource source = ImageSource.FromUri(new Uri("http://alexander.vreeswijk.eu/memento/" + App.TemplateSource + template.FileName));
TemplateSource templateSource = new TemplateSource { Id = template.Id, Source = source, WidthHeight = WidthHeight, FileName = template.FileName };
sourceList.Add(templateSource);
}
CurrentTemplateCountReceived = sourceList.Count;
}
else
{
HitBottomOfList = true;
}
}
}
bool handling = false;
public async void MyHandler()
{
// already handling an event, ignore the new one
if (handling) return;
handling = true;
await LoadTemplateList();
handling = false;
}
}
这是RestService.cs:
HttpClient client;
public string ErrorMessage { get; set; }
public RestService()
{
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
}
public async Task<List<Template>> GetTemplates(User user, int offset)
{
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("un", user.Username));
postData.Add(new KeyValuePair<string, string>("pw", user.Password));
postData.Add(new KeyValuePair<string, string>("offset", offset.ToString()));
var content = new FormUrlEncodedContent(postData);
var weburl = "mysite.org/myapp/get_templates.php";
List<Template> response = await PostResponseTemplates(weburl, content);
return response;
}
public async Task<List<Template>> PostResponseTemplates(string weburl, FormUrlEncodedContent content)
{
var response = await client.PostAsync(weburl, content);
var json = await response.Content.ReadAsStringAsync();
if (json != "Nothing")
{
var jObject = JObject.Parse(json);
var templatePropery = jObject["Templates"] as JArray;
List<Template> templateList = new List<Template>();
foreach (var property in templatePropery)
{
List<Template> propertyList = new List<Template>();
propertyList = JsonConvert.DeserializeObject<List<Template>>(property.ToString());
templateList.AddRange(propertyList);
}
var sourcePropery = (JObject)jObject["Source"];
foreach (var property in sourcePropery)
{
string tempplateSource = property.Value.Value<string>();
App.TemplateSource = tempplateSource;
}
return templateList;
}
else
{
ErrorMessage = json;
return default(List<Template>);
}
}
ICommand
LoadTemplates => new Command(MyHandler);
在CollectionView几乎到达列表底部时被调用,因此它将获取更多数据。然后,我创建了MyHandler
,以检查是否有一个正在忙于网络通话的事件以获取更多数据,因为它多次触发该事件。最后,它执行从我的网页获取数据的onLoadingTemplates
。
现在首次在构造函数中使用LoadTemplateList();
运行时,一切正常,但是在执行它时,就像:await LoadTemplateList();
,当触发事件时,它在RestService.cs的以下行崩溃:var response = await client.PostAsync(weburl, content);
与错误:
'对象引用未设置为对象的实例。'
有人可以告诉我为什么在触发事件时获取数据时会发生这种情况吗?
在这里做一些侦探工作。
因为您说过您得到了NullReferenceException
对象引用未设置为对象的实例。
在线
var response = await client.PostAsync(weburl, content);
weburl
或content
都不能为空,因为它是先前在GetTemplates
方法中创建的,因此只有在前一行中client
为null
的可能性仍然存在:如果是这样,您创建客户端后,应确保在客户端中设置以下属性:
httpClient.DefaultRequestHeaders.ConnectionClose = false;
HttpWebRequest.KeepAlive = true;
MSFT文档中有一个不错的post on HttpClient BestPractices。
希望这会有所帮助!
我可能会押注当前的CollectionView
错误。
这不是“第二次被调用”的情况,但是当您更改已加载的边界ObservableCollection
时,渲染器会崩溃(并且隐藏了CollectionView
的窗口)。
我首先想到的是,它在渲染器中的某个位置正在调用的非UI线程上执行。但是,即使尝试从UI线程修改绑定的ObservableCollection
,渲染器仍然会崩溃。
您可以报告这个错误,我没时间做,实际上只是在使用其他自定义的列表视图。