views:

37

answers:

2

I have a WPF UI Bound to a collection of AwesomeClass

Now, AwesomeClass has a collection of AwesomeParts objects.

How can I make my UI In such a way that (as an example)
for each AwesomeClass instance, there is a Tab on a tab panel and then for each awesome part in that, there is an object on a listbox, on that tab.

Basically: Awesomes->Tabs

And Then : Awesome.Awesomeparts->Tabs.Listbox

A: 

Bind a List<AwesomeClass> to a headered content control. Each "AwesomeClass" object will be set as the datacontext for each "tab" in the headered content control.

Within the content control that is on each "tab", bind the DataContext (AwesomeClass) property that accesses the List<AwesomePart> to your Listbox control.

Make sense?

Cheers.

Dave White
+3  A: 

Hi,

Following is the code to do what you are looking for :

public partial class TabWindow : Window
{
    public TabWindow()
    {
        InitializeComponent();

        List<AwesomeClass> items = new List<AwesomeClass>();

        for (int i = 0; i < 10; i++)
        {
            items.Add(new AwesomeClass());
        }

        AwesomeTabs.ItemsSource = items;

        Loaded += new RoutedEventHandler(TabWindow_Loaded);
    }

    // Method 1
    void TabWindow_Loaded(object sender, RoutedEventArgs e)
    {
        FindListBox(AwesomeTabs);
    }

    private void FindListBox(DependencyObject obj)
    {
        Int32 count = VisualTreeHelper.GetChildrenCount(obj);
        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(obj, i);
            if (child is ListBox)
            {
                (child as ListBox).SelectionChanged += new SelectionChangedEventHandler(ListBox_SelectionChanged);
            }
            else
            {
                FindListBox(child);
            }
        }
    }

    // Method 2
    private void ListBox_Loaded(object sender, RoutedEventArgs e)
    {
        (sender as ListBox).SelectionChanged += new SelectionChangedEventHandler(ListBox_SelectionChanged);
    }

    void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        try
        {
            MessageBox.Show(e.AddedItems[0].ToString());
        }
        catch (Exception)
        { }
    }
}

class AwesomeClass
{
    static Int32 count = 0;

    public Int32 Index { get; set; }

    public List<AwesomePart> Parts { get; protected set; }

    // Method 3 : Preferred
    private AwesomePart _selectedPart;
    public AwesomePart SelectedPart
    {
        get { return _selectedPart; }
        set
        {
            OnSelectionChanged(_selectedPart, value);
            _selectedPart = value;
        }
    }

    private void OnSelectionChanged(AwesomePart oldValue, AwesomePart newValue)
    {
        if (newValue != null) MessageBox.Show(newValue.ToString());
    }

    public AwesomeClass()
    {
        Index = ++count;

        Parts = new List<AwesomePart>();

        for (int i = 0; i < 10; i++)
        {
            Parts.Add(new AwesomePart());
        }
    }

    public override string ToString()
    {
        return "Tab #" + Index.ToString();
    }
}

class AwesomePart
{
    static Int32 count = 0;

    public Int32 Index { get; set; }

    public AwesomePart()
    {
        Index = ++count;
    }

    public override string ToString()
    {
        return "Part #" + Index.ToString();
    }
}

XAML:

<Grid>
    <TabControl Name="AwesomeTabs">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ListBox ItemsSource="{Binding Parts}" SelectedItem="{Binding SelectedPart}" Loaded="ListBox_Loaded"></ListBox>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>
decyclone
The only thing is, If I want to call a function on the selected value of the listbox, how would I reference it?
AKRamkumar
@AKRamkumar: Have a property in the AwesomeClass bound to the Listbox's SelectedItem property. Call the function from the setter of this property.
Veer
Updated the code!
decyclone