Я пытаюсь создать простое приложение для 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>
Чтобы заполнить результат и его элементы, имя и описание, мне нужно получить значения с веб-сервера, который отвечает с помощью json для получениязапрос отправляю.Так как мне нужно делать разные вызовы на сервер, которые отвечают разными объектами json, я поддерживаю разные файлы .cs для каждого, независимо от mainpage.cs (где я только инициализирую, определяю MainPage_Loaded и MainListBox_SelectionChanged).Все данные выбираются и обрабатываются в отдельных файлах .cs.Теперь проблема в том, что когда я делаю httpwebrequest и получаю ответ, пользовательский интерфейс загружается задолго до этого.Как я понял из других постов, BeginGetResponse становится фоновым процессом, и пользовательский интерфейс загружается, чтобы сохранить его отзывчивость.Таким образом, чтобы подвести итог перед возвратом веб-запроса с данными с сервера, пользовательский интерфейс загружается как пустой, так как данные не заполняются.Теперь я не могу использовать Dispatcher для заполнения, поскольку я не нахожусь в MainPage.cs и поэтому не могу получить прямой доступ к списку.Я также пробовал перезвонить, но безуспешно.Пожалуйста, помогите
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 я пытаюсь заполнить пользовательский интерфейс.Но к тому времени, когда элемент управления входит в BeginGetResponse, мой пользовательский интерфейс заполнен и в populateResult, так как список не доступен, MainListBox недоступен. Я не могу использовать диспетчер для обновления пользовательского интерфейса с новыми данными
.более подробная информация, результатом является 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;
???
}
}
Вероятно, я должен признать это (???), где я застрял.Коллекция результатов обновляется, но не в пользовательском интерфейсе.Пользовательский интерфейс все еще пуст, и я не могу получить доступ к MainListBox из populateRsult для обновления.Надеюсь, это понятно.В противном случае, пожалуйста, скажите мне
С учтивостью позвольте мне также предоставить 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));
}
}
}
SubviewModel:
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));
}
}
}