Возможно ли адаптивное наложение контролов на изображение в WPF?

Задача сделать SCADA программку мониторинга техпроцесса. В WPF, в качестве window background размещено изображение, на которое я разместил множество label. Но при изменении разрешения экрана, закономерно, контролы съезжают. Возможно ли с таким подходом к задаче как размещение поверх изображения каких либо элементов WPF получить адаптивную к разрешению экрана программу? Каким способом лучше "оживить изображение"? Буду благодарен за подсказку, на данном этапе даже не знаю с какой стороны к этому подойти.

введите сюда описание изображения

введите сюда описание изображения

<Window x:Class="IUS_OKO.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:IUS_OKO"
    mc:Ignorable="d"
    Title="MainWindow" Height="900" Width="1600" WindowStyle="None" WindowState="Maximized" ResizeMode="NoResize">
<Window.Background>
    <ImageBrush ImageSource="/IUS_OKO.png"/>
</Window.Background>
<Grid>

    <!--ph параметры-->

    <Label Name="Ph_OKO_Pulp" ToolTip="Ph_OKO_Pulp" Content="3.42" HorizontalAlignment="Left" Margin="87,128,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="Ph_OKO_Washout1" Content="6.0" HorizontalAlignment="Left" Margin="60,283,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="Ph_OKO_Washout2" Content="0.0" HorizontalAlignment="Left" Margin="60,319,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="Ph_OKO_Well898" Content="6.0" HorizontalAlignment="Left" Margin="415,397,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="Ph_OKO_SandTank1" Content="0.9" HorizontalAlignment="Left" Margin="1102,170,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="Ph_OKO_SandTank2" Content="4.0" HorizontalAlignment="Left" Margin="1296,170,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>
    <Label Name="GL_OKO_SandTank3" Content="67" HorizontalAlignment="Left" Margin="1504,170,0,0" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" FontFamily="Arial Black" FontSize="20"/>

    <!--Дискретные уровни на емкости (аварийный, высокий, средний и низкий уровни)-->

    <Label Name="LevelDiscreteEmergency_Reactor_OKO1" HorizontalAlignment="Left" Margin="210,270,0,0" VerticalAlignment="Top" Height="25" Width="25" Background="Red" BorderBrush="{x:Null}"/>
    <Label Name="LevelDiscreteHigh_Reactor_OKO1" HorizontalAlignment="Left" Margin="210,294,0,0" VerticalAlignment="Top" Height="22" Width="25" Background="Lime" BorderBrush="{x:Null}"/>
    <Label Name="LevelDiscreteMedium_Reactor_OKO1" HorizontalAlignment="Left" Margin="210,315,0,0" VerticalAlignment="Top" Height="24" Width="25" Background="Lime" BorderBrush="{x:Null}"/>

Ответы (1 шт):

Автор решения: aepot

Подход примерно такой

  1. Выбрасываете PNG
  2. Берёте Canvas фиксированной ширины и высоты, например 1200×800
  3. Рисуете на канвасе что угодно с помощью XAML: прямоугольниками, треугольниками, эллипсами, линиями и т.д. Можно даже Path как в SVG, почитайте что-нибудь про это. Можно TextBlock для текста добавить.
  4. Канвас засовываете во ViewBox, и кладёте всё вместе в окно

Так как изображение векторное, оно идеально будет растягиваться вьюбоксом вместе с окном без пикселизации и смещения элементов.

Учите XAML, он очень много всего умеет включая красивые анимации.

К тому же любой элемент можно нарисовать однократно, а затем его переиспользоввть сколько угодно раз. То есть добавить или убрать кран или бочку не составит труда.


Ну и в альтернативу самое простое решение проблемы "в лоб" с фоновой картинкой.

Берите тот же Grid с тем же фоном.

<ViewBox>
    <Grid Width="ширина картинки" Height="высота картинки">
        <Grid.Background>
            <ImageBrush ImageSource="/IUS_OKO.png"/>
        </Grid.Background>

        <!-- ваши контролы с пиксельным позиционированием по картинке -->
    </Grid>
</ViewBox>

И кладите это всё в окно. В этом случае абсолютное позиционирование сработает.

Но даже если вы всё на 1000% сделаете правильно, всё равно при изменении окна оно будет на +-пиксель ездить туда-сюда. Если хочется идеальной красоты на всех разрешениях, надо отказаться от фоновой PNG и всё полностью рисовать в XAML.

И последнее: Grid это не просто панель-прямоугольник, а таблица. В этой панели можно задавать строки и колонки, и позиционировать элементы относительно строк и колонок, а не относительно левого верхнего угла.

→ Ссылка