"Two-dimensional" UserControl

214 Views Asked by At

I am trying to implement a custom user control.

Let's consider the ViewModels:

public class FileViewModel
{
    public string Name { get; set; }
    public BitmapSource Thumbnail { get; set; }
}

public class DirectoryViewModel
{
    public string Name { get; set; }
    public ObservableCollection<FileViewModel> Files { get; private set; }
    public FileViewModel SelectedFile { get; set; }
}

I want to have the UserControl which display such ViewModels in this way (two ways):

1) Two dimensional list-like control.

2) Two dimensional coverflow-like control.

Please note that each file has it's Thumbnail and each directory remembers last-viewed file. Directory should display last-viewed file thumbnail (as its own) if the directory is not selected.

Directories selection is changed by using left-right keys and appropriate buttons. Files selection is changed by using up-down keys and appropriate buttons.

Have anyone implemented some two-dimensional UserControl like this?

Best regards, Serge.

1

There are 1 best solutions below

2
On

I can think of two ways to approach it, but I don't have a compiler with me right now to test either way out.

  • Method one would be to overwrite the Template of something like a ListBox (since you want to track the SelectedItem) so that the SelectedItem is always in the same spot. Changing the SelectedItem (via mouse or arrow keys) will simply move the new item to the center of the list.

    This can be used for both the Files and Directories. Make the Directories use a Horizontal version of the Template, and have it's ItemTemplate for the SelectedItem (use a DataTrigger) contain a Vertical version of the template for Files.

  • The other way I could think of doing it is with ItemsControls and sub-collection showing the next/previous 3 files/directories.

    You can use Linq statements to get the Previous/Next collections based on the initial collection and current item. For example, MyCollection.Skip(MyCollection.IndexOf(SelectedItem)).Take(3)

    <Grid>
        <RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefintiion Height="Auto" />
            <RowDefinition Height="*" />
        </RowDefinitions>
        <ColumnDefinitions>
            <ColumnDefinition Height="*" />
            <ColumnDefinition Height="Auto" />
            <ColumnDefinition Height="*" />
        </ColumnDefinitions>

        <!-- Previous 3 Files -->
        <ItemsControl Grid.Row="0" Grid.Column="1"
                      ItemsSource="{Binding Previous3Files}"
                      ItemTemplate="{StaticResource FileTemplate}"
                      ItemsPanel="{Binding VerticalStackPanel}" />

        <!-- Next 3 Files -->    
        <ItemsControl Grid.Row="2" Grid.Column="1"
                      ItemsSource="{Binding Next3Files}"
                      ItemTemplate="{StaticResource FileTemplate}"
                      ItemsPanel="{Binding VerticalStackPanel}" />

        <!-- Previous 3 Directories-->
        <ItemsControl Grid.Row="1" Grid.Column="0"
                      ItemsSource="{Binding Previous3Directories}"
                      ItemTemplate="{StaticResource DirectoryTemplate}"
                      ItemsPanel="{Binding HorizontalStackPanel}" />

        <!-- Next3 Directories-->
        <ItemsControl Grid.Row="1" Grid.Column="2"
                      ItemsSource="{Binding Next3Directories}"
                      ItemTemplate="{StaticResource DirectoryTemplate}"
                      ItemsPanel="{Binding HorizontalStackPanel}" />

        <!-- Current Item -->
        <ContentControl Grid.Row="1" Grid.Column="1"
                        Content="{Binding SelectedFile}"
                        ContentTemplate="{Binding FileTemplate}" />
        </ContentControl>
    
    </Grid>