Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I draw subdivide a databound rectangle in the XAML?

Tags:

c#

wpf

I'm creating an application which displays rows of tables according to a map config file. Right now, I have XAML that displays the outer bound of the rectangle in the correct location, but I can't find any information on drawing subdividing lines, which are held in the data source as numTablesWide and numTablesTall.

Here's the XAML that draws the box in the correct location

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <!-- Selection stuff -->
        </Setter>

        <Setter Property="Canvas.Top" Value="{Binding y}"/>
        <Setter Property="Canvas.Left" Value="{Binding x}"/>

        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="Padding" Value="5"/>
        <Setter Property="Panel.ZIndex" Value="{Binding z}" />

        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Path Data="{Binding data}" Stroke="{Binding brush}" StrokeThickness="2" Stretch="Fill"/>
                        <TextBlock Text="{Binding i}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <DataTrigger Binding="{Binding type}" Value="tableBlock">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Grid>
                                <Rectangle Fill="{Binding fill}" Stroke="Black" StrokeThickness="5"
                                           Width="{Binding width}" Height="{Binding height}" Panel.ZIndex="50"/>
                                <TextBlock Text="{Binding id}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            </Grid>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</ListBox.ItemContainerStyle>

current and objective images

Thanks!

like image 680
Benjin Avatar asked Nov 10 '22 10:11

Benjin


1 Answers

Here is a solution i used when i needed to draw a grid, lets see if the solution fits all your needs. There is no simple way to draw the inner lines of your rectangles, or at least i am not aware of one. If you think the problem a little different, there is an easy way to achieve the result from your second screen.

What i see when i look at a figure from the second screen?

I see a rectangle which is divided in a few equally sized rectangles.

The question becomes: How can i draw the inner grid using single rectangle and setting up a Tile effect ?

Using a VisualBrush. The only additional work you have to do is to calculate the size of your inner rectangles, which is a simple property in your ViewModel:

public Rect tileRect
{
    get { return new Rect(0, 0, width / numTablesWide, height / numTablesTall); }
}

And the ContentTemplate using the VisualBrush is:

<DataTemplate>
    <Grid>
        <Rectangle 
            Stroke="Black" 
            StrokeThickness="4"
            Width="{Binding width}" Height="{Binding height}">
            <Rectangle.Fill>
                <VisualBrush 
                    TileMode="Tile" 
                    Viewport="{Binding tileRect}" 
                    ViewportUnits="Absolute">
                     <VisualBrush.Visual>
                         <Rectangle 
                            Stroke="Black" 
                            StrokeThickness="2" 
                            Fill="{Binding fill}"
                            Width="{Binding tileRect.Width}" 
                            Height="{Binding tileRect.Height}" />
                     </VisualBrush.Visual>
                 </VisualBrush>
             </Rectangle.Fill>
         </Rectangle>
     </Grid>
</DataTemplate>

The ViewModel tileRect property returns a Rect since you cannot bind the Width and Height properties of a Rect object.

The result: input: x=100, y=50, height=222, width=398, numTablesTall=2, numTablesWide=4

Grid drawn with VisualBrush

like image 156
Novitchi S Avatar answered Nov 14 '22 21:11

Novitchi S