views:

130

answers:

4

I need to draw a graph like bus station schema: o-School----o-Church-------o-Police.
So, simple line and circles. Also I need to zoom it.

As I have VS 2010, I thought WPF(as I understood it uses vectorized graphics) should be the good canvas to start drawing.

Is it possible, complicated, and what do you recommend for a WPF beginner.

Thanks.

EDIT: Can I set a DashStyle for the line (dash-dot, dotDot...)?

+1  A: 

It is easy to draw simple shapes in WPF. You can find them in the Shapes namespace with some examples.

An example for you:

<Canvas>
    <Ellipse Canvas.Top="0" Canvas.Left="0" Width="256" Height="256" />
    <Line Canvas.Top="0" Canvas.Left="256" X1="0" Y1="0" X2="128" Y2=128" >
</Canvas>
BlueCode
Can I set a DashStyle for the line (dash-dot, dotDot)?
serhio
+1  A: 

Here's something that could help you get started. It has a Canvas containing a few shapes, and a Slider control that allows you to control zooming. You can just add other elements inside the Canvas as required.

<DockPanel>
    <Slider x:Name="slider" Minimum=".1" Maximum="10" Value="1" DockPanel.Dock="Top"/>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Canvas Width="300" Height="300">
                <Canvas.LayoutTransform>
                    <ScaleTransform ScaleX="{Binding ElementName=slider, Path=Value}"
                                ScaleY="{Binding ElementName=slider, Path=Value}"/>
                </Canvas.LayoutTransform>

                <Ellipse Canvas.Left="10" Canvas.Top="10" Width="20" Height="20"
                        Stroke="Black" StrokeThickness="1" Fill="Red"/>
                <Line Canvas.Left="20" Canvas.Top="30" X1="0" X2="0" Y1="0" Y2="50" 
                    Stroke="Black" StrokeThickness="1"/>
                <Ellipse Canvas.Left="10" Canvas.Top="80" Width="20" Height="20"
                        Stroke="Black" StrokeThickness="1" Fill="Yellow"/>
            </Canvas>
        </Border>
    </ScrollViewer>
</DockPanel>

EDIT:

To change the dash style for the line, simply set the StrokeDashArray property. It allows you to specify the pattern for how your line looks like. It follows a "segment length, gap length, segment length, gap length..." format, so setting this line:

<Line Canvas.Left="100" Canvas.Top="100" Stroke="Black"
                          X1="0" X2="100" Y1="0" Y2="0"
                          StrokeThickness="3" StrokeDashArray="2,2"/>

gives you this (i.e. a line made up of a series of segments with a length of 2 followed by gaps with a length of 2):

alt text

Setting the StrokeDashArray to

StrokeDashArray="5,1,1,1"

gives you the dash-dot pattern.

alt text

karmicpuppet
Can I set a DashStyle for the line (dash-dot, dotDot)?
serhio
Yes. Check this out: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/aa1d9ef1-2f04-4db5-86f9-5eaad67105b5
karmicpuppet
See EDIT for an example. =)
karmicpuppet
+1  A: 

This should not be complicated, I would keep it simple by putting a Canvas within a Viewbox. Increase the Canvas' Width and Height to zoom out, and Decrease them to zoom in.

  <DockPanel>
    <Viewbox DockPanel.Dock="Top" Width="100" Height="100" >
      <Canvas Width="{Binding Path=Value, ElementName=TheZoomSlider}" Height="{Binding Path=Value, ElementName=TheZoomSlider}">
        <Ellipse Stroke="Black" Canvas.Top="40" Canvas.Left="20" Width="20" Height="20" />
        <Ellipse Stroke="Black" Canvas.Top="40" Canvas.Left="50" Width="20" Height="20" />
        <Ellipse Stroke="Black" Canvas.Top="40" Canvas.Left="80" Width="20" Height="20" />
      </Canvas>
    </Viewbox>
    <Slider Margin="0,400,0,0" HorizontalAlignment="Center" Orientation="Vertical" DockPanel.Dock="Bottom" Name="TheZoomSlider" Minimum="20" Maximum="800" Value="40" />
    </DockPanel>
Khyad Halda
Can I set a DashStyle for the line (dash-dot, dotDot)?
serhio
+1  A: 

You have a few examples using Canvas and showing Zoom but if you only need a single line of elements you can use a StackPanel and set VerticalAlignment="Center" then you don't need to calculate the positions just the sizes of the lines.

alt text

    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
    <StackPanel.Resources>
        <Style TargetType="Ellipse">
            <Setter Property="Width" Value="20" />
            <Setter Property="Height" Value="20" />
            <Setter Property="Stroke" Value="Orange" />
            <Setter Property="StrokeThickness" Value="3" />
        </Style>
        <Style TargetType="Line">
            <Setter Property="Stroke" Value="DodgerBlue" />
            <Setter Property="StrokeDashArray" Value="5,1,1,1,1,1" />
            <Setter Property="StrokeThickness" Value="2" />
        </Style>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="White" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Padding" Value="4" />
        </Style>
        <Style TargetType="Border" x:Key="Label">
            <Setter Property="Background" Value="LimeGreen" />
            <Setter Property="CornerRadius" Value="10" />
        </Style>
    </StackPanel.Resources>
    <Ellipse />
    <Border VerticalAlignment="Center">
        <Line X2="50" />
    </Border>
    <Border Style="{StaticResource Label}">
        <TextBlock Text="Home" />
    </Border>
    <Border VerticalAlignment="Center">
        <Line X2="50" />
    </Border>            
    <Ellipse />
    <Border VerticalAlignment="Center">
        <Line X2="50" />
    </Border>
    <Border Style="{StaticResource Label}">
        <TextBlock Text="Church" />
    </Border>
    <Border VerticalAlignment="Center">
        <Line X2="50" />
    </Border>            
    <Ellipse />
    <Border VerticalAlignment="Center">
        <Line X2="20" />
    </Border>
    <Border Style="{StaticResource Label}">
        <TextBlock Text="Police" />
    </Border>
</StackPanel>

If you need to do multiple diagrams you can create a different DataTemplate for each type of node e.g circle, road, label and use an ItemsControl with a ItemsPanelTemplate set to do the same thing.

Kris
Can I set a DashStyle for the line (dash-dot, dotDot)?
serhio
I updated my sample to have a dashed line. See http://msdn.microsoft.com/en-us/library/system.windows.shapes.shape.strokedasharray.aspx for details of how DashArray works. I also changed the sample to use styles for the elements so you can adjust the appearance in one place instead of multiple places, this makes the code a bit longer but it's easier to manage.
Kris