I'm a WPF n0ob and I'm struggling with selecting the appropriate control to get the layout I want.
What I'm trying to do is draw a bunch of squares (virtual post-it notes) onto the screen. Each note is going to be a decent size (~150 pixels or so) and there could be hundreds of these notes. I want the whole thing to be scrollable so that you can resize the window however you like and the whole thing should be zoomable.
I've done this and it works.
But what I've done seems awfully wrong....
In the code, I'm dynamically creating post it notes and adding them to a giant canvas. I'm manually doing the math to determine where to place each note and how big the canvas should be. I added some labels at the top and had to go back and add a 'Y Offset' value to push all the squares down. I actually generate three different canvas controls and then add each one of them to a stack panel that is inside of a ScrollViewer. I added a scroll bar and set the the stack panel to zoom in and out as you adjust the bar.
It 'works', but I feel like I'm really not using WPF the way it's meant to be used. I tried achieving the same thing with a grid, but the grid didn't seem to want to size itself appropriately.
Can someone tell me a 'better' way to achieve the same look?
Here's my Xaml code - as you can see; there isn't much to it....
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="25" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Slider x:Name="ZoomSlider" Minimum="0.01" Value="1" Maximum="2" Margin="0,0,0,6" />
    <ScrollViewer x:Name="MyScroller" Grid.Row="1" HorizontalScrollBarVisibility="Visible"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
        <StackPanel x:Name="TicketsGrid"  Background="White" HorizontalAlignment="Center">
        </StackPanel>
    </ScrollViewer>
</Grid>
And then here is what I'm doing in code (ugly!!!)
For Each myWorkItem As WorkItem In myWorkItems
        Dim newRect As New Border
        newRect.Width = TicketSizeX
        newRect.Height = TicketSizeY
        If myWorkItem.State.ToUpper.Contains("HOLD") Then
            newRect.Background = New SolidColorBrush(Colors.Purple)
        Else
            newRect.Background = New SolidColorBrush(Color)
        End If
        newRect.CornerRadius = New System.Windows.CornerRadius(5)
        newRect.BorderThickness = New System.Windows.Thickness(1)
        newRect.BorderBrush = New SolidColorBrush(Colors.Black)
        Dim myPanel As New StackPanel
        newRect.Child = myPanel
        Dim lblTitle As New Label
        lblTitle.Content = myWorkItem.Id
        lblTitle.FontWeight = System.Windows.FontWeights.Bold
        Dim lblDesc As New TextBlock
        lblDesc.Text = myWorkItem.Title
        lblDesc.TextWrapping = TextWrapping.Wrap
        myPanel.Children.Add(lblTitle)
        myPanel.Children.Add(lblDesc)
        newRect.SetValue(Canvas.LeftProperty, CType(((TicketCount Mod TicketsXPerUser) * TicketStepX) + (xOffset * TicketStepX * TicketsXPerUser), Double))
        newRect.SetValue(Canvas.TopProperty, CType(((Math.Floor((TicketCount / TicketsXPerUser)) * TicketStepY)) + NameLabelHeight, Double))
        myCanvas.Children.Add(newRect)
        TicketCount += 1
    Next
    MyCanvas.Width = (TicketStepX * TicketsXPerUser) * myTFS.SharedCodeTeam.Count
    MyCanvas.Height = (CType(((Math.Floor((MaxTicket / TicketsXPerUser)) + 1) * TicketStepY), Double))
    TicketsGrid.Children.Add(MyCanvas)