[英]ListBox not populated in WP7 after values return from web request
我正在尝试从头开始为WP7构建一个简单的应用程序。 MainPage.xaml中的列表框如下所示:
<Grid x:Name="ContentPanel" Grid.Row="1" >
<ListBox x:Name="MainListBox" ItemsSource="{Binding result}" SelectionChanged="MainListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding name}" TextWrapping="Wrap" />
<TextBlock Text="{Binding description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
为了填充结果及其元素,名称和描述,我需要从Web服务器获取值,该Web服务器使用json响应我发送的get请求。 由于我需要对服务器进行不同的调用以响应不同的json对象,因此我为每个服务器维护了不同的.cs文件,与mainpage.cs无关(我仅在其中初始化,定义MainPage_Loaded和MainListBox_SelectionChanged)。 所有数据都在单个.cs文件中提取和处理。 现在的问题是,当我进行httpwebrequest并检索到响应时,UI早于此加载。 据我从其他帖子中了解到,BeginGetResponse成为后台进程,并且加载了UI以使其保持响应状态。 因此,总结一下,在Web请求与服务器中的数据一起返回之前,由于未填充数据,因此UI被加载为空白。 现在,由于我不在MainPage.cs中,因此无法使用Dispatcher进行填充,因此无法直接访问列表框。 我也尝试了回调,但没有成功。 请帮忙
MainPage.cs:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
this.Loaded +=new RoutedEventHandler(MainPage_Loaded);
}
private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (MainListBox.SelectedIndex == -1)
return;
NavigationService.Navigate(new Uri("/DetailsPage.xaml?selectedItem=" + MainListBox.SelectedIndex, UriKind.Relative));
MainListBox.SelectedIndex = -1;
}
// Load data for the ViewModel Items
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
App.ViewModel.LoadData();
}
}
LoadData()本质上初始化请求参数,准备URI并将HTTP请求发送到另一个类(executeRequest.cs文件)中的另一个函数,该类获取响应并将请求处理为可以映射到的对象:
public void decodeJson<E>(HttpWebRequest request)
{
request.Method = "GET";
var reqresult = (IAsyncResult)request.BeginGetResponse(ResponseCallback<E>, request);
}
public void ResponseCallback<E>(IAsyncResult reqresult)
{
var request = (HttpWebRequest)reqresult.AsyncState;
var response = (HttpWebResponse)request.EndGetResponse(reqresult);
if (response.StatusCode == HttpStatusCode.OK)
{
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
if (contents.ToString().StartsWith("{\"jsonrpc"))
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(contents)))
{
Type typeofe = typeof(E);
var deserializer = new DataContractJsonSerializer(typeof(E));
E element = (E)deserializer.ReadObject(ms);
populateResult<E>(element);
}
}
}
}
在populateResult中,我试图填充UI。 但是,当控件进入BeginGetResponse时,由于列表框,MainListBox无法访问,因此我的UI已填充并在populateResult中,我无法使用分派器用新数据刷新 UI
为了提供更多信息,结果是一个类的ObservableCollection,该类包含来自json的不同属性
populateResult非常简单:
private void processResult<E>(E element)
{
//Checking for the type of result so that I can map
string typeis = typeof(E).ToString();
if (typeis.EndsWith("MyViewModel")
{
App.ViewModel.result = (element as MyViewModel).result;
???
}
}
也许我应该承认这个(???)是我被困住的地方。 结果集合已更新,但不在UI中。 UI仍然是空白,我无法从populateRsult访问MainListBox进行更新。 希望清楚。 否则请告诉我
出于礼貌,我还提供MyViewModel和SubViewModel
MyViewModel:
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel()
{
this.result = new ObservableCollection<SubViewModel>();
}
public ObservableCollection<SubViewModel> result { get; set; }
private string _sampleProperty = "Sample Runtime Property Value";
public string SampleProperty
{
get
{
return _sampleProperty;
}
set
{
_sampleProperty = value;
NotifyPropertyChanged("SampleProperty");
}
}
public bool IsDataLoaded
{
get;
private set;
}
public void LoadData()
{
//Initialize all the parameters
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format
(uri with parameters);
request.Method = "GET";
//call the decide json to get the reponse and parse it
executeRequest execReq = new executeRequest();
execReq.decodeJson<MyViewModel>(request);
this.IsDataLoaded = true;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
子视图模型:
public class SubViewModel : INotifyPropertyChanged
{
private string _name;
public string name
{
get
{
return _name;
}
set
{
_name = value;
NotifyPropertyChanged("name");
}
}
private string _description;
public string description
{
get
{
return _description;
}
set
{
_description = value;
NotifyPropertyChanged("description");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我看不到有关如何将内容绑定到列表框的任何信息。 你有一个结合result
在XAML中,但并未显示,它实际上是什么声明。 如果它是一个可观察的集合,则populateResult
方法应该非常简单,只需使用新数据更新可观察的集合的内容即可。
如果要在填充结果中重新创建可观察的集合,而不仅仅是更改其内容,那可能就是您的问题。
更新:
最大的问题(从更新后的代码可以看出)是,在设置result
时,您的视图模型没有引发属性更改。 因此,您需要执行以下两项操作之一:
a)在result
上添加属性更改支持,例如视图模型类对SampleProperty
,以便在对其进行修改时,绑定可以看到更改:
private ObservableCollection<SubViewModel> _result = new ObservableCollection<SubViewModel>();
public ObservableCollection Result
{
get
{
return _result;
}
set
{
_result = value;
NotifyPropertyChanged("Result");
}
}
// -- elsewhere --
private void processResult<E>(E element)
{
// (why were you using the type **name** to check the
// type of the result instead of just using `as`?)
var model = element as MyViewModel;
if (model != null)
{
App.ViewModel.Result = model.result;
}
}
b)否则您不需要设置 result
,而是修改其内容,因为它已经是一个可观察的集合:
private void processResult<E>(E element)
{
var model = element as MyViewModel;
if (model != null)
{
// result is an ObservableCollection, so just modify its contents.
// anything bound to it will see the changes via collection change notifications
App.ViewModel.result.ClearItems();
foreach (var x in model.result)
App.ViewModel.result.Add(x);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.