I had LOTS of questions on my post "Rebinding Controls in Windows Presentation Foundation" about how do you access these items immediately after rebinding-and lots of advice.

The advice I received was:

 

  1. Don't bind in code only XAML
  2. Be async, watch for the property to change, then continue doing whatever else needs done.
  3. Be async, post your own work item at a lower priority – maybe BeginInvoke(DispatcherPriority.Background,…)
  4. Be sync, flush out the queue of pending work items like this:
    Dispatcher.Invoke(DispatcherPriority.Background, (DispatcherOperationCallback) delegate(object unused){return null;}, null);

In looking at these suggestions the first one (to not do data binding in code) wasn't going to work as in my application was already bound in the XAML.

-What i needed to do was rebind it. Therefore option #4: forcing a synchronous call sounded good as synchronous is nice and easy with the only code needed something like the following:

Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, (System.Windows.Threading.DispatcherOperationCallback)delegate(object unused) { return null; }, null);

Unfortunately this wasn't working as the work for inserting the items into the listbox wasn't even in the work queue yet (remember I am binding over the internet).  Which left me with option #2 and #3.  Luckily option #2 was only two additional lines of code and a handler function...probably the most elegant solution anyway.  I am going to be updating the WPF Hands On Labs with this but you can find an easy to repurpose example below:

 

private void Button1_Click(object sender, RoutedEventArgs e)

        {

XmlDataProvider mydata = new XmlDataProvider();

mydata.Source = new Uri("http://203.147.133.54/teched/questions.xml");

mydata.XPath = "//Question[@QID=2]/Answer[@isCorrect='true']";

Binding mybinding = new Binding();

mybinding.Source = mydata;

mybinding.NotifyOnTargetUpdated = true; //added

Binding.AddTargetUpdatedHandler(Listbox1, new EventHandler<DataTransferEventArgs>(BindingTargetUpdated)); //added

BindingOperations.SetBinding(Listbox1, ItemsControl.ItemsSourceProperty, mybinding);

}

private void BindingTargetUpdated(object sender, DataTransferEventArgs e)

        {

            Button1.Content = Listbox1.Items.Count.ToString();         

        }

 

 

Assuming something like the following XAML:

 

<Window x:Class="WpfApplication1.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

>

<Grid>

<ListBox  Margin="7,74,4,71" Name="Listbox1"/>

<Button Height="42" Margin="99,0,114,16" Name="Button1" Click="Button1_Click">Button</Button>

</Grid>

</Window>

 

Big thanks to Dwayne Need and Paul Stovell