Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Simple DataMatrix

Tags:

c#

wpf

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.

like image 389
Florian Avatar asked May 02 '26 23:05

Florian


1 Answers

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");
}
like image 184
Rachel Avatar answered May 05 '26 12:05

Rachel