views:

378

answers:

2

I'm trying to pupulate one of three listboxes from a (fourth) source list box. The source has a list of school Subjects which are classified as elementary, middle or high school subjects. The source listbox is a list of checkboxes. The user clicks on the checkbox and one of the other three are intended to get a copy of the Subject object from the source list. I've got the thing wired up and successfully hit a CheckBox_Changed method. I can successfully locate the Subject instance from the source list and add it to the target list's Source array.

What I can't do is show the update on the Silverlight control that the target array is bound to.

Any ideas?

Thanks

private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
  var cb = (CheckBox)sender;
  var children = ((Grid)cb.Parent).Children;
  // cb has a sibling TextBlock item that has the index of the item in 
  //   the list of subjects
  var ch2 = children[1] as TextBlock;
  var subjectIndexStr = ch2.Text;
  var myWorkingSubject = workingSubjectList[int.Parse(subjectIndexStr)];

  switch (myWorkingSubject.SubjectLevelId)
  {
// updates to the elementarySubjects, middleSubjects and highSubjects 
//    don't get reflected in the lists that use them as a resource.
    case (int)SubjectLevels.Elementary:
      elementarySubjects.Add(myWorkingSubject);
      break;
    case (int)SubjectLevels.Middle:
      middleSubjects.Add(myWorkingSubject);
      break;
    case (int)SubjectLevels.High:
      highSubjects.Add(myWorkingSubject);
      break;
    default: break;

  }
}   

// this is how the target classes are declared.
public class SubjectsElementary : ObservableCollection<WorkingSubject>
{
}
public class SubjectsMiddle : ObservableCollection<WorkingSubject>
{
}
public class SubjectsHigh : ObservableCollection<WorkingSubject>
{
}

Here are snippets from the .xaml file

<TutorRouterSvc:WorkingSubjectList x:Key="subjects" />
<TutorRouterSvc:SubjectsElementary x:Key="elementarySubjects" />
<TutorRouterSvc:SubjectsMiddle x:Key="middleSubjects" />
<TutorRouterSvc:SubjectsHigh x:Key="highSubjects" />


  <ListBox x:Name="subjectList" ItemsSource="{Binding Mode=OneWay, Source={StaticResource subjects}}">

  <ListBox.Resources>

  </ListBox.Resources>
  <ListBox.ItemTemplate>
   <StaticResource ResourceKey="DataSubjectsTemplate1"/>
  </ListBox.ItemTemplate>
 </ListBox>

<Grid Grid.Column="1">
  <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
  </Grid.RowDefinitions>

  <ListBox Margin="0,0,8,0" x:Name="elementarySubjectList" 
   ItemsSource="{Binding Mode=OneWay, Source={StaticResource elementarySubjects}}"
    Background="#FFE75151" Grid.Row="0">
    <ListBox.ItemTemplate>
      <StaticResource ResourceKey="DataSubjectsTemplate1"/>
    </ListBox.ItemTemplate>
  </ListBox>
  <ListBox Margin="0,0,8,0" x:Name="middleSubjectList" 
   ItemsSource="{Binding Mode=OneWay, Source={StaticResource middleSubjects}}"
    Background="#FFE75151" Grid.Row="1">
    <ListBox.ItemTemplate>
      <StaticResource ResourceKey="DataSubjectsTemplate1"/>
    </ListBox.ItemTemplate>
  </ListBox>
  <ListBox Margin="0,0,8,0" x:Name="highSubjectList" 
   ItemsSource="{Binding Mode=OneWay, Source={StaticResource highSubjects}}"
    Background="#FFE75151" Grid.Row="1">
    <ListBox.ItemTemplate>
      <StaticResource ResourceKey="DataSubjectsTemplate1"/>
    </ListBox.ItemTemplate>
  </ListBox>
</Grid>
A: 

I'm not quite sure, but this may be fixable by doing the changes inside a Dispatch.BeginInvoke().

You could refactor the switch statement to a new method called UpdateListBox, then call it:

Dispatcher.BeginInvoke(() => UpdateListBox(myWorkingSubject.SubjectLevelId))
Glen Little
Thanks for the response. I can't say I understand what the Dispatcher.BeginInvoke() does except initiate a deligate on a queue. I was thinking that simply adding a new element to the bound data collection would be enough. What would UpdateListBox() do to update the ListBox?
A: 

Maybe this is happening because the XAML is Newing up a new instance of your objects, which it's databinding to.

Try adding this to the cosntructor on your Page.xaml.cs (or where ever the control is located);

_subjects = Resources["subjects"] as WorkingSubjectsList;
_elementarySubjects = Resources["elementarySubjects"] as SubjectsElementary;

etc...

Maybe that will help. I've implemented the same concept by binding listboxes to Observable collections on several occassions and haven't experienced what you're encountering.

I do have a couple of suggestions: have you tried this on your check changed event?

workingsubject _item = workingSubjectList[subjectsList.selectedindex];
switch (_item.SubjectLevel) //I'm assuming this property as you have the ID and it looks to be an enumeration
        {
            case Elementary:
             elementarySubjects.Add(_item):
             break;
            case Middle:
             middleSubjects.Add(_item):
             break;
            case High:
             highSubjects.Add(_item):
             break;
                case default:
                        throw new Exception("Unrecognized Subject Level");
        }

hth.