Binding to binding of two listboxes

Let’s imagine following thing. I have list of projects and list of employees, assigned to those projects. Now I want to select some projects and see employees’ assignments – who’s going to work overtime. Simple, yes? We just create two listboxes. One binded to the list pro projects, and the second is binded to the selected items of first listbox with converter, that calculate unique employees and return calculated result. Something like this. Here we can clearly see, that Employee 12 already forgot how his kids looks like.

 

      <ListBox Name=prjs SelectionMode=Extended ItemsSource={StaticResource projects}/>

      <ListBox Name=emps1 ItemsSource={Binding ElementName=prjs, Path=SelectedItems, Converter={StaticResource myConv}}/>

Do it. You’ll notice very fast, that your converter myConv will be called only once, when you have nothing selected, so it simple impossible to convert selected values to something, we need.  You know what, it makes sense, why I should reinitialize converter, if my types are not going to change?

Let’s try another trick. We’ll put shared datasource in application resource level and on SelectionChanged event put our stuff there. After it we’ll just bind second listbox to this source.

 

<l:Employees x:Key=employees/>

<l:Projects x:Key=projects/>

 

 

<ListBox Name=prjs SelectionMode=Extended ItemsSource={StaticResource projects} SelectionChanged=onSelection/>

<ListBox Name=emps ItemsSource={Binding Source={StaticResource employees}}/>

 

 

void onSelection(object sender, SelectionChangedEventArgs e)

        {

            Employees emps = this.Resources["employees"] as Employees;

 

            if (emps != null)

            {

                for (int i = 0; i < e.RemovedItems.Count; i++)

                {

                    Project p = e.RemovedItems[i] as Project;

                    for (int j = 0; j < p.Employees.Count; j++)

                    {

                        if (emps.Contains(p.Employees[j]))

                        {

                            if(emps[emps.IndexOf(p.Employees[j])].Width == 0)

                            {

                                emps.Remove(p.Employees[j]);

                            }

                            else

                            {

                                emps[emps.IndexOf(p.Employees[j])].Width–;

                            }

                        }

                    }

                }

 

                for (int i = 0; i < e.AddedItems.Count; i++)

                {

                    Project p = e.AddedItems[i] as Project;

                    for (int j = 0; j < p.Employees.Count; j++)

                    {

                        if (!emps.Contains(p.Employees[j]))

                        {

                            emps.Add(p.Employees[j]);

                        }

                        else

                        {

                            emps[emps.IndexOf(p.Employees[j])].Width++;

                        }

                    }

                }

            }

        }

Now it’s works. The only thing we have to do is create simple datatemplate to visualize an employee assignment.

 

    <DataTemplate DataType={x:Type l:Employees} x:Key=emp>

      <TextBlock FontSize={Binding Path=Width, Converter={StaticResource wts}} Text={Binding Path=Name}/>

    </DataTemplate>

That’s all folks, not always we should go straight-forward to get what we need from WPF, but it’s looks like no really obstacles can be found there.

Source code for this article

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DotNetKicks
  • DZone
  • Live
  • Reddit
  • TwitThis
  • email
  • Slashdot
  • StumbleUpon

You may also be interested with:

  1. Real singleton approach in WPF application
  2. INotifyPropertyChanged auto wiring or how to get rid of redundant code

No comments yet

Leave a Reply

Recommended

 


Sponsor


Partners

WPF Disciples
Dreamhost
Code Project
Switched to Better Place

Together