3

I am starting a quite big Project in the next days and I thought about what's the best way to create the project. And now I have an important question on a control I don't really know what's the BEST way to do implement it.

I have a matrix of led lights. (32x16 leds). These have to be displayed in a grid and now that the tricky part. I have to be able to do quite a lot of things with them. As example I have to be able to access the databound leds quite easy do some operations like shift all of them 2 times right or left or invert them and so on.

I thought about displaying them in an itemcontrol like this:

<ItemsControl ItemsSource="{Binding Path=Leds}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Rows="16" Columns="32"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type local:Led}">
                <Ellipse Name="ellipse" Fill="Green"/>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding Path=State}" Value="Off">
                        <Setter TargetName="ellipse" Property="Fill" Value="Red"/>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

But how should I handle the mouseclicks on the led to turn it or of. (I am using MVVM) And how would you abstract the whole grid within the leds?

There are many solutions but I don t know which one to take?

May you have an interesting idea how to create a simple and CLEAN solution.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Florian
  • 5,918
  • 3
  • 47
  • 86
  • add properties to your Led object mode: maybe an UniqueID so when mousedown event fired on ellipse you can handle turn on/off and I think Leds it's a List so you can use some linq methods to quick handle massive turn on/off and so on – michele Aug 09 '12 at 13:30

2 Answers2

2

Instead of a UniformGrid, consider using a regular Grid in your ItemsControl and binding the Grid.Column and Grid.Row in the ItemContainerStyle to a value on your object. This will make it much easier to do things like shift entire columns or rows.

You could write out 16 and 32 Row/Column definitions, or I have some attached properties on my blog that would let you do this with one line each.

<ItemsControl ItemsSource="{Binding Leds}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid local:GridHelpers.RowCount="16"
                  local:GridHelpers.ColumnCount="32" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            ...
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

As for clicking them to turn them on/off, wrap each item in a Button tag and overwrite the Template to look the way you want. Then you can bind the Command event to a property in your ViewModel, and pass it the selected LED as a CommandParameter

<Button Command="{Binding RelativeSource={RelativeSource ItemsControl}, Path=DataContext.ToggleLedCommand}"
        CommandParameter="{Binding }">
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Ellipse Name="ellipse" Fill="Green"/>
            <ControlTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=State}" Value="Off">
                    <Setter TargetName="ellipse" Property="Fill" Value="Red"/>
                </DataTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
   </Button.Template>
</Button>

And your Command implementation would simply be

void ToggleLed(LedModel led)
{
    led.State = (led.State == "On" ? "Off" : "On");
}
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • of course that would be a solution but not that easy and clean above. With your solution I have to create Attachedproperties and so on. above I just have to set the itemssource and i am nearly finished. The idea with the command is ok but I would say I dont need a button because I can apply a Inputbinding nearly every element – Florian Aug 10 '12 at 07:24
0

Instead of using an UniformGrid, I'd rather advice you to use the excellent DataGrid2D control introduced in this stackoverflow thread

It'd allow you to bind your DataGrid2D's ItemsSource to a 2D object, in your case, a Led[,] , and then will display any of your changes in the 2D array. Assume you want to switch two leds, like from position [1,2] to [2,5], you'd just have to do it on your Led[,] array and the view will update itself accordingly

Community
  • 1
  • 1
Damascus
  • 6,553
  • 5
  • 39
  • 53