views:

92

answers:

2

I have a datagrid based selection control that duplicates the Easing Function selector in Expression Blend. This is for the Easing Function project so you will also be helping yourself :)

This selector is a permanent fixture on the screen, to make it easy to try out options, while still looking enough like the options you normally select from a drop-down in Blend:

alt text

I need to stop the current cell moving into the last "Heading" column.

Is there an easy way to restrict movement into columns so that only the first 3 columns are selectable?

+2  A: 

I'd be inclined to do something like this:-

 <Grid>
    <Grid.ColumnDefinitions>
       <ColumnDefinition Width="150" />
       <ColumnDefinition Width="50" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
       <RowDefinition />
       <RowDefinition Height="250" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2">
       <!-- Heading Text Blocks -->
    </StackPanel>
    <ListBox ItemsSource="{Binding SetOfFunctions}" Grid.Row="1">
       <ListBox.ItemsPanel>
           <ItemsPanelTemplate>
               <toolkit:WrapPanel />
           </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
    </ListBox>
    <ItemsControl ItemsSource="{Binding SetOfFunctionNames}" Grid.Row="1" Grid.Column="1" />
  </Grid>

Thats a basic skeleton idea, the only selector here is the ListView, appropriate sizing and ordering of source collections will arrive at the desired appearance.

AnthonyWJones
@AnthonyWJones: Very interesting solution. I especially like the single list converting to 3 columns part (currently I use an SQL triple join to flatten the results). Will try that out tonight. Will the WrapPanel allow for correct Up, Down, left and Right key navigation (like a DataGrid)?
Enough already
@AnthonyWJones: in the middle of updating the control to try your example, but where did you get a Silverlight ListView from? Thanks.
Enough already
@HiTech: Sorry had a brain-fade, dealing with multiple control frameworks. I meant the standard ListBox, edited accordingly.
AnthonyWJones
@AnthonyWJones: Shame... I tried that last night, but a standard Listbox only keyboard navigates in one dimension (along the list of options) and this needs up/down/left/right (like a grid).
Enough already
@HiTech: A little sub-classing and some interceptions of `OnKeyDown` ought to do it. If I get a chance I'll see if can build a `WrapBox` that's a version of `ListBox` allowing for this kind of directional navigation.
AnthonyWJones
I am throwing away some points to get a real code answer on this one. Feel free to give it a go.
Enough already
Your solution really just highlights the problem. Controls should not know how to or whether to select their objects. That information should be provided to the control dynamically, without reflection and without doing weird template hackery. I'll see if I can demonstrate what the appropriate solution is, but won't have time this week to collect the bounty.
What I mean is that you are trying to take advantage of the fact ItemsControl does not expose a Selector like ListView does. Your solution implicitly argues that you should think in terms of Controls w/ or w/o Selector abstract (virtual) classes. I am saying that is silly. What is important is that your Control lets you express the problem domain w/o exposing encapsulation details. An EasingFunction Viewer should not let you navigate to a description because that object has no navigable links.
@user429921: Sounds really clever and I'm sure the computer scientists will probably agree, I on the other hand have no idea what you are on about.
AnthonyWJones
A: 

Conceptually, the WPF and SL DataGrid stinks. Anything that requires dynamic relationships among rows and columns is hackish. For example, a cell's value cannot be computed at run-time w/o reflection on UI bindings, and is determined by the DataGrid's hardwired strategy for displaying a value in a cell. It assumes that Columns display a specific object in a Data Source, and it assumes that it knows how to walk that data source. (For what it is worth, I've argued this "successfully" (their words, not mine) to at least one WPF UI component vendor, and they might create a DataGrid that works this way.) If you're familiar with Ext.js, that's how DataGrid's work in that HTML/CSS/JS framework: DataGrid's have no knowledge of what to do with a DataSource, you have to tell it what to do. Everything is completely modularized and there is very little hardwiring of dependencies that can't be overwritten without reflection.

You are better off creating your own DataGrid-like control, especially if you don't have a large number of rows or columns to materialize. Your control should let you walk the DataSource however you want and supply information on how to render the cell and edit the cell. The cell editor should probably implement a Flyweight pattern to conserve memory, but only because that is a standard trick.

@user429921: I'm after a code solution and would be happy to accept a hacked Grid implementation as AnthonyWJones suggested (even code-behind at this point is welcome). Just need something in there for now, can always replace it later with a real custom control. Thanks anyway for the suggestions.
Enough already
I'm not interested in the bounty, per se (although it is nice to collect rep so I can then offer bounty if I ever have hard questions I need answers to). I am more interested in the nice use case you presented for a better DataGrid. I've read various hacks to these sorts of WPF/SL DataGrid issues on the WPF forums, and to me they are all non-satisfactory. I just haven't pushed myself to completely create a DataGrid from scratch because it is a lot of work. :)