2017-01-30 1 views
0

Je travaille sur un projet qui récupère des adresses à partir de l'API de Google. J'obtiens une réponse de google, mais j'ai des problèmes pour afficher les résultats de l'adresse (AddressList) sur radgridview. J'utilise une application WPF et j'ai juste besoin d'afficher les résultats dans RADGRIDVIEW. J'utilise 'ItemSource' pour essayer de lier à la grille, mais j'obtiens l'erreur suivante: Invalid Cross Thread Access.Lier une liste à Telerik RadGridView à l'aide de l'application WPF

CODE

public partial class AddressSearch : ContentAppEntityView 
{ 
    public AddressSearch() 
    { 
     InitializeComponent(); 
    } 

    HttpWebRequest request = null; 

    #region **********SEARCHING********** 

    private void addressInput_GotFocus(object sender, RoutedEventArgs e) 
    { 
     if (addressInput.Text == "Search") 
      addressInput.Text = ""; 
     else 
      addressInput.SelectAll(); 
    } 

    private void addressInput_LostFocus(object sender, RoutedEventArgs e) 
    { 
     if (addressInput.Text == String.Empty) 
     { 
      addressInput.Text = "Search"; 
      searchclose.Opacity = 0; 
     } 
     else if (addressInput.Text == "Search") 
      searchclose.Opacity = 0; 
    } 

    private void EmptySearch_Click(object sender, RoutedEventArgs e) 
    { 
     addressInput.Text = "Search"; 
     searchclose.Opacity = 0; 
    } 

    private void addressInput_KeyDown(object sender, KeyEventArgs e) 
    { 
     searchclose.Opacity = 1; 
    } 

    private void Enter_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.Key == Key.Enter) 
     { 
      var address = addressInput.Text; 

      var requestUri = string.Format("http://localhost/media/TextToSpeech/TextToSpeechService.svc/getDataProxy?url=https://maps.googleapis.com/maps/api/geocode/json?address={0}&key=AIzaSyCgsNpuUoH7m6U7lqeZjlLZ3MgM15PW15o", Uri.EscapeDataString(address)); 
      //var requestUri = string.Format(ConfigurationManager.GetAppSetting("addressSearchGeoCode", Uri.EscapeDataString(address))); 

      HttpWebRequest request = WebRequest.Create(requestUri) as HttpWebRequest; 
      request.Method = "GET"; 
      IAsyncResult result = request.BeginGetResponse(new AsyncCallback(RequestCompleted), request); 
      var dodo = result; 
     } 
    } 

    private void RequestCompleted(IAsyncResult result) 
    { 
     var request = (HttpWebRequest)result.AsyncState; 
     var response = (HttpWebResponse)request.EndGetResponse(result); 
     Stream stream = response.GetResponseStream(); 

     try 
     { 
      StreamReader reader = new StreamReader(stream); 
      string text = reader.ReadToEnd(); 

      Regex rgx = new Regex("<.*\\>"); 
      string newResult = rgx.Replace(text, ""); 

      JObject json = JObject.Parse(newResult); 
      JArray results = (JArray)json["results"]; 

      List<double> latList = new List<double>(); 
      List<double> lngList = new List<double>(); 
      List<string> AddressList = new List<string>(); 

      if (results.Count == 0) 
      { 
       MessageBox.Show("No results found"); 
      } 
      else 
      { 
       foreach (JObject obj in results) 
       { 
        if (obj == null) 
        { 
         MessageBox.Show("Address returned no results"); 
        } 
        string formattedAddress = (string)obj["formatted_address"]; 
        AddressList.Add(formattedAddress); 

        double lat = (double)obj["geometry"]["location"]["lat"]; 
        latList.Add(lat); 

        double lng = (double)obj["geometry"]["location"]["lng"]; 
        lngList.Add(lng); 
        //TODO Add exception handling 
       } 
       this.addressGrid.ItemsSource = AddressList; 
      } 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Error" + ex.Message); 
     } 

    } 

} 

Section de XAML

<!--Address Results--> 
<telerik:RadGridView Grid.Row="2" AutoGenerateColumns="True" x:Name="addressGrid" Margin="0 0 0 18" 
     ItemsSource="{Binding}" CanUserFreezeColumns="False" CanUserSelect="False" 
     EnableColumnVirtualization="True" EnableRowVirtualization="True" ShowGroupPanel="False" ScrollViewer.VerticalScrollBarVisibility="Visible" 
     CanUserDeleteRows="True" RowIndicatorVisibility="Collapsed" DataLoadMode="Asynchronous" HeaderRowStyle="{StaticResource ZoneActivityHeaderRowStyle}" 
     GroupPanelStyle="{StaticResource GroupPanelStyle}" Background="#00000000" VerticalGridLinesBrush="#00000000" HorizontalGridLinesBrush="#00000000" AlternationCount="2" 
     RowHeight="32" ShowColumnHeaders="False" RowStyle="{StaticResource ActivityRowStyle}" AlternateRowStyle="{StaticResource ActivityAlternateRowStyle}"> 

    <telerik:RadGridView.Columns> 

     <telerik:GridViewDataColumn Header="Targetting" Width="28" IsReadOnly="True" IsFilterable="False" ShowDistinctFilters="True" IsGroupable="False"> 
      <telerik:GridViewDataColumn.CellTemplate> 
       <DataTemplate> 
        <ctrl:TargetButton x:Name="targetButton" VerticalAlignment="Center" HorizontalAlignment="Center" /> 
       </DataTemplate> 
      </telerik:GridViewDataColumn.CellTemplate> 
     </telerik:GridViewDataColumn> 

     <telerik:GridViewDataColumn Header="Address" Width="*" IsReadOnly="True" 
       IsFilterable="False" ShowDistinctFilters="True" IsGroupable="False"> 
      <telerik:GridViewDataColumn.CellTemplate> 
       <DataTemplate> 
        <Grid> 
         <TextBlock Text="{Binding}" Foreground="White" FontFamily="Segoe UI" 
            FontSize="12" VerticalAlignment="Top" Margin="5" TextWrapping="Wrap" /> 
         <Border Background="#00000000" Height="32" Margin="-5 0" /> 
        </Grid> 
       </DataTemplate> 
      </telerik:GridViewDataColumn.CellTemplate> 
     </telerik:GridViewDataColumn> 

    </telerik:RadGridView.Columns> 
    </telerik:RadGridView> 

    <TextBlock Text="No addresses available" FontFamily="Segoe UI Semibold" FontSize="12" Foreground="#FFFFFF" Grid.Row="2" Margin="18" Visibility="{Binding AddressCollection.Count}" /> 
</Grid> 

Répondre

1

Le RadGridView ne peut être consulté sur le fil sur lequel il a été créé à l'origine. Vous pouvez utiliser le répartiteur pour renvoyer tous les appels à RadGridView vers le thread d'interface utilisateur. Essayez ceci:

private void RequestCompleted(IAsyncResult result) 
{ 
    var request = (HttpWebRequest)result.AsyncState; 
    var response = (HttpWebResponse)request.EndGetResponse(result); 
    Stream stream = response.GetResponseStream(); 

    try 
    { 
     StreamReader reader = new StreamReader(stream); 
     string text = reader.ReadToEnd(); 

     Regex rgx = new Regex("<.*\\>"); 
     string newResult = rgx.Replace(text, ""); 

     JObject json = JObject.Parse(newResult); 
     JArray results = (JArray)json["results"]; 

     List<double> latList = new List<double>(); 
     List<double> lngList = new List<double>(); 
     List<string> AddressList = new List<string>(); 

     if (results.Count == 0) 
     { 
      Dispatcher.BeginInvoke(new Action(() => MessageBox.Show("No results found"))); 
     } 
     else 
     { 
      foreach (JObject obj in results) 
      { 
       if (obj == null) 
       { 
        Dispatcher.Invoke(new Action(() => MessageBox.Show("Address returned no results"))); 
       } 
       string formattedAddress = (string)obj["formatted_address"]; 
       AddressList.Add(formattedAddress); 

       double lat = (double)obj["geometry"]["location"]["lat"]; 
       latList.Add(lat); 

       double lng = (double)obj["geometry"]["location"]["lng"]; 
       lngList.Add(lng); 
       //TODO Add exception handling 
      } 
      Dispatcher.Invoke(new Action(() => this.addressGrid.ItemsSource = AddressList)); 
     } 

    } 
    catch (Exception ex) 
    { 
     Dispatcher.Invoke(new Action(() => MessageBox.Show("Error" + ex.Message))); 
    } 
} 
+0

Dispatcher est exactement ce dont j'avais besoin. Cela a fonctionné parfaitement. – developerME

1

Sonne comme il est parce que vous essayez de mettre à jour un objet qui est lié à l'interface utilisateur d'un fil non-UI. Pour que cela fonctionne, vous devez demander au répartiteur de faire la mise à jour pour vous comme ceci.

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
        new Action(() => 
        { 
         //Do something 
        })); 

Personnellement, j'utiliser le cadre MVVM Light qui a la classe DispatcherHelper donc je peux écrire un code comme celui-ci

    DispatcherHelper.CheckBeginInvokeOnUI(() => 
        { 
         //Do something 
        }); 
+0

J'aurais pu faire ce trajet et ça aurait bien marché. Pour mon programme cependant, j'ai décidé d'aller avec @ mm8. Mais merci pour votre réponse! Cela pourrait s'avérer utile à l'avenir. – developerME