1

I'm having a hard time implementing a Miller Column interface in WPF, and was wondering if anyone has seen an implementation I could borrow from. I've done some searching and can't find anything myself.

Currently I have my data organized in a hierarchy so that it can be placed in a TreeView, but I'd like to add the Miller Column view as an option in my program.

gregsdennis
  • 7,218
  • 3
  • 38
  • 71
  • My suggestion is to explore the possibility to restyle the default template for the wpf treeview. – michele May 22 '12 at 13:36

2 Answers2

1

The UI for Miller Columns looks like multiple linked ListBox controls.

Here's an example: WPF MVVM hierarchy selected item

Community
  • 1
  • 1
Phil
  • 42,255
  • 9
  • 100
  • 100
  • That's only good if you have a static hierarchy. What if you're looking at a file system (as can be viewed in a Mac Finder window)? You need an indefinite number of `ListBox`es. – gregsdennis May 22 '12 at 15:01
  • 1
    I you need a dynamic number of columns you could use an ItemsControl with a horizontal StackPanel at the ItemsPanel. The ItemTemplate would contain a ListBox. If you need splitters between each ListBox, then you need a Grid, but you'll have to manage the number of columns using code behind. – Phil May 22 '12 at 15:07
  • that's exactly the approach I'm taking. I'm working on an example to post. – gregsdennis May 22 '12 at 15:10
1

UPDATE I've enhanced my solution in a couple blog posts that can be found here and here. The new version allows for a more generic approach using MVVM.

A possible solution came to me, and Phil confirmed that it was the right approach. I have to use an ItemsControl with a horizontal StackPanel as the ItemsPanel. Then I created a DataTemplate for my data type and used it for the ItemTemplate on my ItemsControl.

The data template:

<DataTemplate x:Key="DataNodeStackedDataTemplate" DataType="my:DataNode">
    <ListBox ItemsSource="{Binding Children}"
             Style="{StaticResource StackedListBoxStyle}"/>
</DataTemplate>

The ItemsControl:

<ItemsControl x:Name="MillerColumnsView" VerticalContentAlignment="Stretch"
              ItemTemplate="{StaticResource DataNodeStackedDataTemplate}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

The code-behind:

private void StackedListBox_SelectionChanged(object sender,
                                             SelectionChangedEventArgs e)
{
    var lb = sender as ListBox;
    if (lb == null) return;
    var dn = lb.DataContext as DataNode;
    if (dn == null) return;
    int index = MillerColumnsView.Items.IndexOf(dn);
    if (index == -1) return;
    index++;
    while (MillerColumnsView.Items.Count > index)
        MillerColumnsView.Items.RemoveAt(index);
    if (dn.Children == null) return;
    // this Select() call performs some restructuring of the tree to 
    // appropriate display the correct nodes in the next ListBox
    dn.Select(dn.AvailableItems.ElementAt(lb.SelectedIndex));
    if (dn.Children.Count() == 0) return;
    MillerColumnsView.Items.Add(dn.Children.ElementAt(0));
}

This automatically removes and creates ListBoxes for each level of selection. A little syling and it could look pretty, too!

gregsdennis
  • 7,218
  • 3
  • 38
  • 71