如何将 WP7 接口绑定到我异步检索的数据?
我正在开发一个 Windows Phone 7 应用程序,该应用程序允许用户查看其 Chargify.com 帐户下每个“站点”的统计信息。
我一直在关注复数视觉培训视频,该视频让我大部分时间都到了那里,但是我的数据来自复杂的来源,并且他们硬编码了一个列表。
因此,设置如下:
模型:
public SiteStats
{
public string seller_name { get; set;}
public static GetSiteStatistics(string subdomain, string apiKey)
{
SiteStats retVal = null;
HttpWebRequest request = WebRequest.Create(string.Format("https://{0}.chargify.com/stats.json", subdomain)) as HttpWebRequest;
NetworkCredential credentials = new NetworkCredential(apiKey, "X");
request.Credentials = credentials;
request.Method = "GET";
request.Accept = "application/json";
request.BeginGetResponse(result =>
{
using (var response = request.EndGetResponse(result))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string stats = reader.ReadToEnd();
retVal = Json.Deserialize<SiteStats>(stats);
}
}
}, request);
return retVal;
}
}
ViewModel:
public class SiteDetailViewModel : ViewModelBase
{
private SiteStats _siteStats;
public SiteDetailViewModel(string subdomain) : this()
{
this._siteStats = SiteStats.GetSiteStatistics(subdomain, "apiKeyHere");
}
public SiteDetailViewModel : base() { ViewName = "site details"; }
public SiteStats SiteStats
{
get { return _siteStats; }
set {
if (_siteStats != value) {
_siteStats = value;
OnPropertyChanged("SiteStats");
}
}
}
视图:
public partial class SiteDetailView : PhoneApplicationPage
{
private SiteDetailViewModel _viewModel;
public SiteDetailView()
{
InitializeComponent();
Loaded += new RoutedEventHandler(SiteDetailView_Loaded);
}
void SiteDetailView_Loaded(object sender, RoutedEventArgs e)
{
string subdomain = NavigationContext.QueryString["subdomain"];
_viewModel = new SiteDetailViewModel(subdomain);
this.DataContext = _viewModel;
}
}
问题是,当我调用 this.DataContext 时 - _viewModel 成员还没有数据。因此,视图数据绑定 - 但该值为空。
有什么建议吗?一切工作正常,除了视图没有填充数据的绑定控件..
-- Kori
I'm working on a Windows Phone 7 app which allows a user to view the statistics of each of their "sites" under their Chargify.com account.
I've been following a Plural-sight training video which got me most of the way there, however my data is coming from a complex source and they had hard-coded a list.
So, here's the setup:
The model:
public SiteStats
{
public string seller_name { get; set;}
public static GetSiteStatistics(string subdomain, string apiKey)
{
SiteStats retVal = null;
HttpWebRequest request = WebRequest.Create(string.Format("https://{0}.chargify.com/stats.json", subdomain)) as HttpWebRequest;
NetworkCredential credentials = new NetworkCredential(apiKey, "X");
request.Credentials = credentials;
request.Method = "GET";
request.Accept = "application/json";
request.BeginGetResponse(result =>
{
using (var response = request.EndGetResponse(result))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string stats = reader.ReadToEnd();
retVal = Json.Deserialize<SiteStats>(stats);
}
}
}, request);
return retVal;
}
}
The ViewModel:
public class SiteDetailViewModel : ViewModelBase
{
private SiteStats _siteStats;
public SiteDetailViewModel(string subdomain) : this()
{
this._siteStats = SiteStats.GetSiteStatistics(subdomain, "apiKeyHere");
}
public SiteDetailViewModel : base() { ViewName = "site details"; }
public SiteStats SiteStats
{
get { return _siteStats; }
set {
if (_siteStats != value) {
_siteStats = value;
OnPropertyChanged("SiteStats");
}
}
}
The View:
public partial class SiteDetailView : PhoneApplicationPage
{
private SiteDetailViewModel _viewModel;
public SiteDetailView()
{
InitializeComponent();
Loaded += new RoutedEventHandler(SiteDetailView_Loaded);
}
void SiteDetailView_Loaded(object sender, RoutedEventArgs e)
{
string subdomain = NavigationContext.QueryString["subdomain"];
_viewModel = new SiteDetailViewModel(subdomain);
this.DataContext = _viewModel;
}
}
The problem is, that when I call this.DataContext - the _viewModel member doesn't have it's data yet. So, the view databinds - but the value is empty.
Any suggestions? Everything works fine except that the View isn't populating the bound controls to the data ..
-- Kori
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
_viewModel
应该有一个ObservableCollection<>
用于统计信息,并且您将 UI 绑定到该集合。每当向集合中添加或删除项目时,UI 都会自动更新(因为它发出OnPropertyChanged
事件)_viewModel
should have anObservableCollection<>
for the stats and you bind your UI to that collection. Whenever items are added to or removed from the collection, the UI is updated automatically (since it sends out theOnPropertyChanged
event)您的问题不是 WPF,而是 GetSiteStatistics。由于您以异步方式获取结果,因此您的方法几乎总是返回 null,除非碰巧在 GetSiteStatistics 方法返回之前执行 BeginGetResponse。它在任何应用程序中都会失败。
您可以让 GetSiteStatistics 始终创建并返回一个对象,并且仅将其填充到 BeginGetResponse 中。但是你应该确保整个事情是线程安全的。
Your problem is not WPF, but GetSiteStatistics. Since you're getting the result async your method almost always returns null, unless by chance the BeginGetResponse is executed before the GetSiteStatistics method returns. It would fail in any application.
You could have GetSiteStatistics always create and return an object and only fill it in BeginGetResponse. But then you should make sure the whole thing is thread safe.
好吧,我想我已经弄清楚了。
它一直在那里,我只是错过了它。
1)您正在异步获取数据。 “request.BeginGetResponse(result=> .... );”将来的某个时候发生,但您在发生之前返回结果。代码不断移动,它不会等待您的结果。这就是您想要做的:
相关的 ViewModel 代码将如下所示:
这是您需要对 Application 类进行的更改(我不确定这有多线程安全,我真的建议您使用类似 MVVMLight 的东西调度助手。
Alright I got this one figured out I think..
It was there all along I just missed it.
1) you are asynchronously getting data. The "request.BeginGetResponse(result=> .... );" happens sometime in the future, but you return your result before that happens.. the code keeps moving it doesn't wait for your result. Here's what you want to do:
The pertinent ViewModel Code will look something like this:
Here are the changes you need to make to the Application class (I'm not sure how threadsafe this is and I would really recommend that you use something like MVVMLight's DispatcherHelper.