This question is locked. New answers and comments are not allowed.
Having some issues with using the RadDataboundListbox.
I'm using a simple ViewModel that calls an "OnNotifyPropertyChanged" method that, in turn, fires the PropertyChanged event for a list of custom objects. When I use a regular ListBox there isn't any problem...it works fine. When I use the RadDataboundListBox I get an exception when the PropertyChanged event attempts to create a new PropertyChangedEventArgs with the name of the property passed in as a string. I get "The parameter is incorrect".
I originally thought that this was something I was doing because I had a more complicated scenario where the view model was getting created globally. I changed that and I still have the problem.
Also, if I used the RadDataBoundListBox without an itemtemplate and without a datatemplate (using DisplayMemberPath to display listbox items) all was well. The problem seemed to start when I added the data template.
(Edit: I just tested this again - using only DisplayMemberPath - and the problem still occurs.)
I've included here the XAML snippet that includes the RadDataboundListbox and the commented ListBox (I have an identical listbox commented out. That is the piece that works). I've also included code for the view model - but I had to censor the "apikey" variable that I use. This particular application calls out to the NY Times API and that key is assigned to me, so I can't share it. Finally, I included the code-behind for the page. (I've commented out portions of code that were being used to save state for tombstoning purposes...because I thought that might have been a problem as well.)
To add a bit more detail..the listbox is populated after a button press calls the GetMembers() method in the view model. The Session and Chamber properties in the view model are bound to the RadListPicker SelectedItem properties and that is all working fine. There are values in those properties otherwise there would be an issue with the GetMembers() method. The issue doesn't manifest itself until the Members collection attempts a notification that it has changed.
That's about it. Thanks in advance for any guidance.
I'm using a simple ViewModel that calls an "OnNotifyPropertyChanged" method that, in turn, fires the PropertyChanged event for a list of custom objects. When I use a regular ListBox there isn't any problem...it works fine. When I use the RadDataboundListBox I get an exception when the PropertyChanged event attempts to create a new PropertyChangedEventArgs with the name of the property passed in as a string. I get "The parameter is incorrect".
I originally thought that this was something I was doing because I had a more complicated scenario where the view model was getting created globally. I changed that and I still have the problem.
Also, if I used the RadDataBoundListBox without an itemtemplate and without a datatemplate (using DisplayMemberPath to display listbox items) all was well. The problem seemed to start when I added the data template.
(Edit: I just tested this again - using only DisplayMemberPath - and the problem still occurs.)
I've included here the XAML snippet that includes the RadDataboundListbox and the commented ListBox (I have an identical listbox commented out. That is the piece that works). I've also included code for the view model - but I had to censor the "apikey" variable that I use. This particular application calls out to the NY Times API and that key is assigned to me, so I can't share it. Finally, I included the code-behind for the page. (I've commented out portions of code that were being used to save state for tombstoning purposes...because I thought that might have been a problem as well.)
To add a bit more detail..the listbox is populated after a button press calls the GetMembers() method in the view model. The Session and Chamber properties in the view model are bound to the RadListPicker SelectedItem properties and that is all working fine. There are values in those properties otherwise there would be an issue with the GetMembers() method. The issue doesn't manifest itself until the Members collection attempts a notification that it has changed.
That's about it. Thanks in advance for any guidance.
<telerikPrimitives:RadDataBoundListBox x:Name="lboMembers" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding Members}" SelectionChanged="lboMembers_SelectionChanged"> <telerikPrimitives:RadDataBoundListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding FullName}" Width="300" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock Grid.Column="1" Text="{Binding State}" Style="{StaticResource PhoneTextNormalStyle}" /> <TextBlock Grid.Column="2" Text="{Binding Party}" Style="{StaticResource PhoneTextNormalStyle}"/> </Grid> </DataTemplate> </telerikPrimitives:RadDataBoundListBox.ItemTemplate> </telerikPrimitives:RadDataBoundListBox> <!--<ListBox x:Name="lboMembers" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding Members}" SelectionChanged="lboMembers_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding FullName}" Width="300" Style="{StaticResource PhoneTextNormalStyle}" /> <TextBlock Grid.Column="1" Text="{Binding State}" Style="{StaticResource PhoneTextNormalStyle}" /> <TextBlock Grid.Column="2" Text="{Binding Party}" Style="{StaticResource PhoneTextNormalStyle}" /> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox>--> public class MembersVM : INotifyPropertyChanged { private readonly string uriStart = "http://api.nytimes.com/svc/politics/v3/us/legislative/congress/"; private readonly string apiKey = "cannot share this value....."; private string uriString; public MembersVM() { uriString = uriStart + "{0}/{1}/members.xml?api-key=" + apiKey; } #region Methods public void GetMembers() { uriString = string.Format(uriString, Session, Chamber); Uri serviceUri = new Uri(uriString); WebClient client = new WebClient(); //IsBusy = true; client.OpenReadAsync(serviceUri); client.OpenReadCompleted += (s, e) => { List<Member> tmpList = new List<Member>(); ObservableCollection<Member> obsvHolder = new ObservableCollection<Member>(); if (e.Error != null) { // add error message, logging, etc... string sError = e.Error.Message; } else { using (Stream st = e.Result) { XDocument doc = XDocument.Load(st); foreach (var x in doc.Descendants("member")) { tmpList.Add(CreateValidMember(x)); } // Order by state var query = from m in tmpList orderby m.State select m; tmpList = query.ToList(); // Convert list to ObservableCollection foreach (var member in tmpList) { member.FullName = member.FirstName + " " + member.LastName; obsvHolder.Add(member); } // Set the property Members = obsvHolder; } } //IsBusy = false; }; } private Member CreateValidMember(XElement e) { Member m = new Member(); m.Id = e.Element("id").Value; m.FirstName = e.Element("first_name").Value; m.LastName = e.Element("last_name").Value; m.Party = e.Element("party").Value; m.State = e.Element("state").Value; m.ApiUrl = e.Element("api_uri").Value; m.Seniority = e.Element("seniority") != null ? Convert.ToInt32(e.Element("seniority").Value) : 0; m.NextElection = e.Element("next_election") != null ? Convert.ToInt32(e.Element("next_election").Value) : 0; m.MissedPct = e.Element("missed_votes_pct") != null ? Convert.ToDouble(e.Element("missed_votes_pct").Value) : 0; m.PartyLineVote = e.Element("votes_with_party_pct") != null ? Convert.ToDouble(e.Element("votes_with_party_pct").Value) : 0; m.District = Chamber.Equals("House") ? Convert.ToInt32(e.Element("district").Value) : 0; return m; } #endregion #region Properties private ObservableCollection<Member> members; public ObservableCollection<Member> Members { get { return members; } set { if (members != value) { members = value; //this.NotifyPropertyChanged(m => m.Members); OnNotifyPropertyChanged("Members"); } } } private string session; public string Session { get { return session; } set { if (session != value) { session = value; //this.NotifyPropertyChanged(m => m.Session); OnNotifyPropertyChanged("Session"); } } } private string chamber; public string Chamber { get { return chamber; } set { if (chamber != value) { chamber = value; //this.NotifyPropertyChanged(m => m.Chamber); OnNotifyPropertyChanged("Chamber"); } } } private Member selectedMember; public Member SelectedMember { get { return selectedMember; } set { if (selectedMember != value) { selectedMember = value; //this.NotifyPropertyChanged(m => m.SelectedMember); OnNotifyPropertyChanged("SelectedMember"); } } } #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion public void OnNotifyPropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(p)); } } }public partial class MainPage : PhoneApplicationPage { private MembersVM vm; // Constructor public MainPage() { InitializeComponent(); vm = new MembersVM(); DataContext = vm; } private void btnGo_Click(object sender, RoutedEventArgs e) { vm.GetMembers(); } private void lboMembers_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (lboMembers.SelectedItem != null) { vm.SelectedMember = lboMembers.SelectedItem as Member; NavigationService.Navigate(new Uri("/MemberDetail.xaml", UriKind.Relative)); } } //protected override void OnNavigatedFrom(NavigationEventArgs e) //{ // State["members"] = App.AppVM.Members; // State["session"] = App.AppVM.Session; // State["chamber"] = App.AppVM.Chamber; //} //protected override void OnNavigatedTo(NavigationEventArgs e) //{ // if (State.ContainsKey("members") && State.ContainsKey("session") && State.ContainsKey("chamber")) // { // App.AppVM.Members = State["members"] as ObservableCollection<Member>; // App.AppVM.Session = State["session"] as string; // App.AppVM.Chamber = State["chamber"] as string; // } //} }