Member 11830457 Ответов: 1

Как наложить холст для представления слоев типов объектов, чтобы я мог показывать/скрывать определенные слои?


Поэтому, честно говоря, я уже ставил этот вопрос на StackOverflow, не получая никаких особенно полезных ответов, я признаю, что могут быть, возможно, лучшие способы структурирования кода, но я хочу частично понять ограничения объекта Canvas (если действительно это проблема), и поскольку было два варианта:
голоса на SO предполагают использование "ItemControls as layers", почему этот метод может быть лучшим решением.

Итак, я намеревался наложить несколько холстов, от 4 до 6 слоев, поверх большого изображения, чтобы я мог установить все объекты в данном холсте как видимые или невидимые с простотой процедуры показа или скрытия в классе слоев. UpdateLayers просто имеет набор вызовов для каждого слоя.Обновление(). В случае слоя settlementNames может показаться, что код обновления не выполняет свою работу. Это должно работать так;
private void ShowCities_Click(object sender, RoutedEventArgs e)
{
    UpdateLayers();
    settlements.Show(Settlements);
    settlementNames.Show(SettlementNames);
}

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


Это прекрасно работало с первым холстом, содержащим растровые изображения размером с иконку в ZIndex 1 (большое изображение по существу является фоном с ZIndex 0). Когда я попытался добавить еще один холст в ZIndex 2, код прошел, как и ожидалось, но не показал содержимое. На этот раз содержимое представляет собой набор текстовых блоков.

Свойство AssociatedCanvas в коде было проверено и является правильным экземпляром Canvas, который был заложен в главном окне XAML.

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);
}


XAML выглядит примерно так:

<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>


Что я уже пробовал:

Я задавался вопросом, является ли размер изображения и, следовательно, холста проблемой, 21600 x 10800 пикселей, потому что после замены этого изображения на гораздо меньшее изображение 400 x 400, меньшее, чем обычно было бы у ScrollViewer, функция show hide для второго холста ("имена поселений") работала . Но голый в уме я мог бы показать/скрыть Нижний холст ZOrder ("поселения") без проблем. Может быть, это ограничение памяти?

1 Ответов

Рейтинг:
0

Gerry Schmitz

Почему вы вообще беспокоитесь о "множественных холстах"?

"Слои" - это логическая конструкция.

Если нет ничего (лишнего), чтобы увидеть, то просто назначьте "слой #" каждому компоненту и "обработайте слой", повторяя один и тот же слой # (скрывая, показывая, окрашивая, что угодно).

Думайте в терминах фильтров.


Member 11830457

Спасибо, что пришел к нам с этим Джерри.

На данный момент это метод проб и ошибок, связанный с поиском альтернативных маршрутов для достижения требуемой функциональности.

Так что, как вы можете догадаться, я новичок в WPF.
Я полагал, что скрытие холста может быть более эффективным методом, чем повторение того, что может быть несколькими тысячами элементов, хотя, конечно, я мог бы ограничить это еще неопределенным числом, только рисуя элементы, которые видны в scrollviewer.

Я думаю, что ваше предложение, вероятно, является лучшим выбором, если просто показать/скрыть холст с помощью одной инструкции-это не вариант. Но тем не менее мне любопытно узнать, в чем проблема с несколькими холстами.