0

I was intending to overlay multiple Canvas, between 4 and 6 layers, on top of a large Image, in order that I can set all objects in a given Canvas as visible or invisable with the simplicity of a show or Hide routine in a layer class. UpdateLayers simply has a set of calls to each layer.Update(). In the case of the settlementNames layer, it would seem that the Update code is not doing its job. It is supposed work like this;

private void ShowCities_Click(object sender, RoutedEventArgs e)
{
    UpdateLayers();
    settlements.Show(Settlements);
    settlementNames.Show(SettlementNames);
}

public void Show(Canvas canvas)
{
    canvas.Visibility = Visibility.Visible;
}

This worked perfectly with the first canvas containing icon sized BitmapImages at ZIndex 1 (the large Image is essentially the background with ZIndex 0). When I tried to add a further canvas at ZIndex 2, the code steps through as expected but does not show the contents. This time the contents is a set of TextBlocks.

The AssociatedCanvas property in the code, has been checked and is the correct Canvas instance, which was laid down in the XAML main window.

public void Update(string layerSelectSqlQuery, LayerType layerType)
{
    DataTable layerDataTable = null;
    int x = -1;
    int y = -1;
    string label;

    using (MySqlClientWrapper db = new MySqlClientWrapper("Server = localhost; Database = tribes;Uid = root;Pwd = xxxxxxxxx;"))
    {
        // TODO add population column - and filter to those settlements considered cities.
        layerDataTable = db.GetDataTable(layerSelectSqlQuery);
    }

    AssociatedCanvas.Children.Clear();

    foreach (DataRow dataRow in layerDataTable.Rows)
    {
        x = (int)dataRow["MapX"];
        y = (int)dataRow["MapY"];
        label = dataRow["Name"].ToString();
        if (x != -1 && y != -1)
        {
            switch (layerType)
            {
                case LayerType.Settlements:
                    DrawBitmapImage(x, y);
                    break;

                case LayerType.SettlementNames:
                    WriteLabel(x, y, label, Color.FromRgb(0, 0, 0));
                    break;

                case LayerType.Units:
                    break;

                case LayerType.UnitNames:
                    break;

                default:
                    break;
            }
        }
    }
}    


Public void WriteLabel(int x, int y, string text, Color color)
{
    TextBlock textBlock = new TextBlock();
    textBlock.Text = text;
    textBlock.Foreground = new SolidColorBrush(color);
    Canvas.SetLeft(textBlock, x);
    Canvas.SetTop(textBlock, y);
    AssociatedCanvas.Children.Add(textBlock);
}

The XAML looks like this in part:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!--<Slider Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Left" Minimum="1" x:Name="slider" />-->
    <ScrollViewer Name="mapScroller" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Grid Name="grid" RenderTransformOrigin="0.5,0.5">
            <Grid.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform x:Name="scaleTransform" />
                </TransformGroup>
            </Grid.LayoutTransform>
            <Viewbox Grid.Column="0" Grid.Row="0" >
                <Image x:Name="MainMap" UseLayoutRounding="True" Stretch="Fill" HorizontalAlignment="Center" VerticalAlignment="Center" 
                       MouseLeftButtonUp="MainMap_MouseLeftButtonUp" Source="{Binding MainTerrainMap}"></Image>
            </Viewbox>
            <Canvas x:Name="Settlements" Panel.ZIndex="1" />
            <Canvas x:Name="SettlementNames" Panel.ZIndex="2" >
            </Canvas>
        </Grid>
    </ScrollViewer>
</Grid>
Andrew Seabrook
  • 397
  • 2
  • 17
  • As a general note, I'd suggest to use a set of ItemsControls as layers. Each ItemsControl would have a Canvas as its ItemsPanel, and have its ItemsSource property bound to a collection of the objects that it is supposed to contain. The ItemTemplate of an individual ItemsControl would define the visual elements used to display the respective items. See e.g. here: https://stackoverflow.com/q/22324359/1136211. For showing or hiding layers, just bind an ItemsControl's Visibility to an appropriate view model property. – Clemens Jan 11 '19 at 22:50
  • Yes this might be an alternative and possibly better way of going about this, I will look into this but as much as anything I want to understand the limitations of using Canvas. Perhaps not the most efficient design choice but why would it not work? – Andrew Seabrook Jan 12 '19 at 12:13
  • No idea. Are you sure that AssociatedCanvas is visible? What if you set its Background property just to check that? – Clemens Jan 12 '19 at 12:39
  • As Clemens said. Itemscontrol. But your basic approach is overly optimistic mate. You wrote a pile of code hoping it would all work. Then found there's a problem somewhere. What you should have done is written a little code with say two canvas and fixed content, proved the showing and hiding. Then iterated. Fix that. Iterate again... and so on. Many iterations means when you change something and it don't work then you know what you just wrote is the problem and its only a bit of work. – Andy Jan 12 '19 at 15:01
  • @Clemens Yes background is Ok, it is visible. I wonder if it is something to do with size however the Image was 21600 x 10800 pixel jpg. Switched this to a 400 x 400 and it is now showing. Canvas limitations perhaps? I have added the XAML to the original text, as this will make things perhaps a little clearer. – Andrew Seabrook Jan 12 '19 at 21:32
  • @Andy - How the hell do you jump to the conclusion that this was not an iterative piece of work. The last iteration was to add the additional Canvas and the WriteLabel routine. Maybe a little iterative self analysis might be useful for you! – Andrew Seabrook Jan 12 '19 at 21:32
  • So still no answer as to why the canvas wont display! – Andrew Seabrook Jan 15 '19 at 18:40

0 Answers0