使用 WPF 应用程序将列表绑定到 Telerik RadGridView

Bind a List to Telerik RadGridView using WPF application

我正在从事一个从 Google 的 API 检索地址的项目。我收到来自 google 的回复,但我无法将地址结果 (AddressList) 显示到 radgridview。我正在使用 WPF 应用程序,只需要将结果显示到 RADGRIDVIEW。我正在使用 'ItemSource' 尝试绑定到网格,但出现以下错误:无效的跨线程访问。

代码

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);
        }

    }

}

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>

听起来像是因为您正在尝试从 non-UI 线程更新绑定到 UI 的对象。为了使其正常工作,您需要要求调度员像这样为您进行更新。

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

我个人使用具有 DispatcherHelper class 的 MVVM-Light 框架,因此我可以编写这样的代码

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

RadGridView 只能在最初创建它的线程上访问。您可以使用调度程序将对 RadGridView 的任何调用编组回 UI 线程。试试这个:

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)));
    }
}