Как: получить размер сетки в пикселях в WPF

Я использую на своей главной странице Pivot с 3 PivotItems.

В каждом PivotItem есть сетка. В одном из них я хочу нарисовать гидравлическую схему. Поэтому я вставил несколько столбцов и строк, чтобы дать каждому элементу фиксированную позицию в ячейке. Мне нужно знать размер сетки, потому что в зависимости от этого размера линии (представляющие трубы контура) располагаются в середине ячейки и имеют половину длины (или высоты в зависимости от направления) ячейки.

Здесь вы можете увидеть, как это должно выглядеть в итоге. Некоторые линии находятся не на своем месте, когда Raspberry 3 подключен к другому дисплею.

Кроме того, экран не полностью заполнен сеткой, так как здесь можно увидеть . Под схемой еще какое-то пустое пространство, но при тех же настройках на других PivotItems этого не происходит.

Когда я хочу получить размер ячейки (все ячейки имеют одинаковый размер! размер с *), используя:

double columnWidth = circuitGrid.ColumnDefinitions[0].ActualWidth;

Я получаю в результате 0.

Когда я использую вместо этого:

double columnWidth = circuitGrid.ColumnDefinitions[0].Width;

Я получаю в результате NaN.

Такое же поведение я использую:

var circuitGridSize = new Size(circuitGrid.ActualWidth, circuitGrid.ActualHeight);

Что я пробовал:

  • используя свойства элемента пользовательского интерфейса Height и ActualHeight
  • использование свойств с типом размера и без него
  • Помещение функции initCircuit в несколько загруженных событий

У кого-нибудь есть решение этой проблемы?

Большое спасибо!

Вот файл MainPage.xaml:

<Page
x:Class="I2cPortExpander.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:I2cPortExpander"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="0">
    <StackPanel>
        <Pivot Margin="0" Height="769" >
            <PivotItem x:Name="AutoMode1" Header="Automatikbetrieb" Margin="0">
                <FlipView>
                    <FlipViewItem>
                        <Grid x:Name="Auto1Grid"  Background="LightGray" Visibility="Visible">
                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                <TextBlock Text="Anzahl der zu prüfenden Kreisläufe:" Style="{ThemeResource BaseTextBlockStyle}"/>
                                <RadioButton x:Name="Option1Cycle" Content="1"  HorizontalAlignment="Center" Checked="Option1Cycle_Checked"/>
                                <RadioButton x:Name="Option2Cycle" Content="2"  HorizontalAlignment="Center" Checked="Option2Cycle_Checked"/>
                                <RadioButton x:Name="Option3Cycle" Content="3"  HorizontalAlignment="Center" Checked="Option3Cycle_Checked"/>
                            </StackPanel>
                        </Grid>
                    </FlipViewItem>
                    <FlipViewItem>
                        <Grid x:Name="Auto2Grid" Background="LightGray" Visibility="Visible">
                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                <TextBlock TextWrapping="Wrap" Text="Festlegen der Zeiten der Prüfschritte in Minuten " Margin="0,0,0,20" FontSize="20"/>
                                <TextBlock x:Name="airTimeText" TextWrapping="Wrap" Text="Druckprüfung mit Luft: 0 Minuten" />
                                <Slider x:Name="airTimeSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="10" Maximum="100" TickPlacement="BottomRight" ValueChanged="airTimeSlider_ValueChanged" />
                                <TextBlock x:Name="cleanTimeText" TextWrapping="Wrap" Text="Spülgang: 0 Minuten"/>
                                <Slider x:Name="cleanTimeSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="10" Maximum="100" TickPlacement="BottomRight" ValueChanged="cleanTimeSlider_ValueChanged"/>
                                <TextBlock x:Name="oilTimeText" TextWrapping="Wrap" Text="Drückprüfung mit Öl: 0 Minuten"/>
                                <Slider x:Name="oilTimeSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="10" Maximum="100" TickPlacement="BottomRight" ValueChanged="oilTimeSlider_ValueChanged"/>
                                <TextBlock x:Name="flowRateTimeText" TextWrapping="Wrap" Text="Durchflussmessung: 0 Minuten"/>
                                <Slider x:Name="flowRateTimeSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="10" Maximum="100" TickPlacement="BottomRight" ValueChanged="flowRateTimeSlider_ValueChanged"/>
                                <TextBlock x:Name="blowTimeText" TextWrapping="Wrap" Text="Ausblasen: 0 Minuten"/>
                                <Slider x:Name="blowTimeSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="10" Maximum="100" TickPlacement="BottomRight" ValueChanged="blowTimeSlider_ValueChanged"/>
                            </StackPanel>
                        </Grid>
                    </FlipViewItem>
                    <FlipViewItem>
                        <Grid x:Name="Auto3Grid" Background="LightGray" Visibility="Visible">
                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                <TextBlock TextWrapping="Wrap" Text="Festlegen der Druckparameter in Bar " Margin="0,0,0,20" FontSize="20"/>
                                <TextBlock x:Name="desiredPressure" TextWrapping="Wrap" Text="Druckprüfung mit: 0 Bar" />
                                <Slider x:Name="desiredPressureSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="2" Maximum="20" TickPlacement="BottomRight" ValueChanged="desiredPressureSlider_ValueChanged" />
                                <TextBlock x:Name="breakPressure" TextWrapping="Wrap" Text="Maximaler Druckverlust während Prüfung: 0 Bar"/>
                                <Slider x:Name="breakPressureSlider" HorizontalAlignment="Center"  VerticalAlignment="Top" Width="500" Margin="0,0,0,20" TickFrequency="1" Maximum="10" TickPlacement="BottomRight" ValueChanged="breakPressureSlider_ValueChanged"/>
                                <Grid>
                                    <Button x:Name="Automatik3_Start" Content="Start" HorizontalAlignment="Right"  VerticalAlignment="Stretch"  Margin="10" Width="75" Click="Automatik3_Start_Click"/>
                                </Grid>
                            </StackPanel>
                        </Grid>
                    </FlipViewItem>
                </FlipView>
            </PivotItem>
            <PivotItem x:Name="HandModus" Header="Handbetrieb" Margin="0">
                <Grid x:Name="circuitGrid" Background="LightGray" Visibility="Visible" Margin="0" >

                    <Grid.RowDefinitions>

                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>

                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>

                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>

                    </Grid.ColumnDefinitions>


                    <Ellipse x:Name="pneuConOuterCirc" Grid.Column="0" Grid.Row="1" Stroke="Black"  HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    <Ellipse x:Name="pneuConInnerCirc" Grid.Column="0" Grid.Row="1" Fill="Black" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    <Button x:Name="HandModeAir" Content="Luft"  HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1"  Background="Gray" Click="HandModeAir_Click"/>
                    <Button x:Name="HandModeCycle1" Content="Kreislauf 1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="3" Grid.Row="0" Background="Gray" Click="HandModeCycle1_Click"/>
                    <Button x:Name="HandModeCycle2" Content="Kreislauf 2" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="3" Grid.Row="1" Background="Gray" Click="HandModeCycle2_Click"/>
                    <Button x:Name="HandModeCycle3" Content="Kreislauf 3" HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Column="3" Grid.Row="2" Background="Gray" Click="HandModeCycle3_Click"/>
                    <Button x:Name="HandModeWaySelector" Content="Pumpe RL" HorizontalAlignment="Stretch"  VerticalAlignment="Top" Canvas.Left="0" Grid.Column="6" Grid.Row="5" Background="Gray" Click="HandModeWaySelector_Click"/>
                    <Button x:Name="HandModePump" Content="Pumpe Aus" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="2" Grid.Row="3" Background="Gray" Click="HandModePump_Click" />
                    <Button x:Name="HandModeMeasureSelector" Content="zu" HorizontalAlignment="Stretch"  VerticalAlignment="Top" Grid.Column="4" Grid.Row="7" Background="Gray" Click="HandModeMeasureSelector_Click" />
                    <TextBlock Text="Werkzeug" Grid.Column="5" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5" >
                        <TextBlock.RenderTransform>
                            <CompositeTransform Rotation="90"/>
                        </TextBlock.RenderTransform>
                    </TextBlock>
                    <Rectangle  Stroke="Black" StrokeThickness="4" Grid.Column="5" Grid.Row="0" Grid.RowSpan="3"/>
                    <Rectangle x:Name="Line1" Grid.Column="0" Grid.Row="1" Height="10" Fill="Green" Width="48" HorizontalAlignment="Right"/>
                    <Rectangle x:Name="Line2" Grid.Column="2" Grid.Row="1" Height="10" Fill="Red" HorizontalAlignment="Stretch" />
                    <Rectangle x:Name="Line4" Grid.Column="2" Grid.Row="2" Width="65" Fill="Red" Height="10" HorizontalAlignment="Right"/>
                    <Rectangle x:Name="Line3" Grid.Column="2" Grid.Row="0"  Fill="Red" Height="10" Width="65" HorizontalAlignment="Right"/>
                    <Rectangle x:Name="Line5" Grid.Column="2" Grid.Row="0"  Fill="Red" Width="10" Height="65" VerticalAlignment="Bottom"/>
                    <Rectangle x:Name="Line6" Grid.Column="2" Grid.Row="1" Width="10" Fill="Red" VerticalAlignment="Stretch" />
                    <Rectangle x:Name="Line7" Grid.Column="4" Grid.Row="0" Height="10" Fill="Red" HorizontalAlignment="Stretch"/>
                    <Rectangle x:Name="Line8" Grid.Column="4" Grid.Row="1" Height="10" Fill="Red" HorizontalAlignment="Stretch"/>
                    <Rectangle x:Name="Line9" Grid.Column="4" Grid.Row="2" Height="10" Fill="Red" HorizontalAlignment="Stretch"/>
                    <Rectangle x:Name="Line10" Grid.Column="6" Grid.Row="0"  Fill="Red" Height="10" Width="65" HorizontalAlignment="Left"/>
                    <Rectangle x:Name="Line11" Grid.Column="6" Grid.Row="1"  Fill="Red" Height="10" Width="65" HorizontalAlignment="Left"/>
                    <Rectangle x:Name="Line12" Grid.Column="6" Grid.Row="2"  Fill="Red" Height="10" Width="65" HorizontalAlignment="Left"/>
                    <Rectangle x:Name="Line13" Grid.Column="6" Grid.Row="0"  Fill="Red" Width="10" Height="65" VerticalAlignment="Bottom"/>
                    <Rectangle x:Name="Line14" Grid.Column="6" Grid.Row="1"  Grid.RowSpan="4" Fill="Red" Width="10"/>
                    <Rectangle x:Name="Line15" Fill="RED" Grid.Column="5" Grid.Row="5" Grid.ColumnSpan="1"  Height="10" HorizontalAlignment="Stretch" VerticalAlignment="Top" />
                    <Rectangle x:Name="Line16" Fill="RED" Grid.Column="3" Grid.Row="5"  Height="10" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
                    <Rectangle x:Name="Line17" Grid.Column="2" Grid.Row="5"  Fill="Red" Height="10" Width="65" VerticalAlignment="Top" HorizontalAlignment="Right" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line18" Fill="Green" Grid.Column="6" Grid.Row="5"  Height="10" Width="65" HorizontalAlignment="Left" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line19" Fill="Green" Grid.Column="3" Grid.Row="5" Grid.ColumnSpan="3" Height="10" HorizontalAlignment="Stretch" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line20" Grid.Column="2" Grid.Row="5"  Fill="Green" Height="10" Width="65" HorizontalAlignment="Right" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line21" Grid.Column="2" Grid.Row="5"  Fill="Green" Width="10" VerticalAlignment="Stretch" Canvas.ZIndex="1" HorizontalAlignment="Left" Margin="59,0,0,0"/>
                    <Rectangle x:Name="Line22" Grid.Column="2" Grid.Row="4"  Fill="Green" Width="10" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line23" Grid.Column="2" Grid.Row="2"  Fill="Red" Width="10" Canvas.ZIndex="1"/>
                    <Rectangle x:Name="Line24" Grid.Column="6" Grid.Row="5"  Fill="Green" Width="10" Height="50" Canvas.ZIndex="1" HorizontalAlignment="Center"/>
                    <Image Source="images/durchfluss.png" Grid.Column="3" Grid.Row="4" Margin="25,25,25,-10"/>
                    <Image Source="images/druckmesser.png" Grid.Column="5" Grid.Row="4" Margin="25,25,25,-10"/>
                </Grid>
            </PivotItem>
            <PivotItem x:Name="Properties" Header="Einstellungen" HorizontalAlignment="Left" Margin="0">
                <Grid>

                </Grid>
            </PivotItem>
        </Pivot>
    </StackPanel>
</Grid>

Here is the MainPage code:

public MainPage()
{

    this.InitializeComponent();

    InitDisplay();

    //this funtion sets up the size of the elements
    initCircuit();

    // Register for the unloaded event so we can clean up upon exit 
    Unloaded += MainPage_Unloaded;

    I2C.InitializeSystem();
}

Вот функция initCircuit:

private void initCircuit()
{

    var displayInformation = DisplayInformation.GetForCurrentView();
    var screenSize = new Size(displayInformation.ScreenWidthInRawPixels,
                              displayInformation.ScreenHeightInRawPixels);
    var circuitGridSize = new Size(circuitGrid.ActualWidth,
                                    circuitGrid.ActualHeight);

    double screenWidth = screenSize.Width;
    double screenHeight = screenSize.Height;


    double rowHeight = circuitGridSize.Height / circuitGrid.RowDefinitions.Count;

    double gridWidth = circuitGrid.Width;


    //Initialisierung des Schaltplanes

    //Initialisierung der Verbindungen

    //Pneumatikanschluss
    pneuConInnerCirc.Height = rowHeight / 2.5;
    pneuConOuterCirc.Height = rowHeight / 2;

    //Werkzeuganschluss
    PathGeometry toolSupplyPathVL = new PathGeometry();
    PathGeometry toolSupplyPathRL = new PathGeometry();



    //Werkzeugsymbol


    //Pumpenanschluss
    PathGeometry pumpSupplyPath = new PathGeometry();


    //Messzweig
    PathGeometry measurePath1 = new PathGeometry();
    PathGeometry measurePath2 = new PathGeometry();


    //Initialisierung der Aktoren des Schaltplans


    //Initialisierung der Messinstrumente
    TextBlock actualPressure = new TextBlock();
    TextBlock actualFlowrate = new TextBlock();

    //-----------------------------------------------//

    //Luftanschluss

    Line1.Width = ((screenWidth / circuitGrid.ColumnDefinitions.Count) - pneuConOuterCirc.Width) / 2;
    Line5.Height = (screenHeight / circuitGrid.RowDefinitions.Count + Line3.Height) / 2;
    Line3.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line4.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line10.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line11.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line12.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line18.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count + Line24.Width) / 2;
    Line17.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line20.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count) / 2;
    Line13.Height = (screenHeight / circuitGrid.RowDefinitions.Count + Line3.Height) / 2;

    HandModeWaySelector.Width = (screenWidth / circuitGrid.ColumnDefinitions.Count);
    HandModeWaySelector.Height = (screenHeight / circuitGrid.RowDefinitions.Count) / 3;

    //  Line24.Height= (screenSize.Height / circuitGrid.RowDefinitions.Count)/2 -HandModeWaySelector.Height;
    // Line24.VerticalAlignment = VerticalAlignment.Stretch;
    Line24.Margin = new Thickness((screenWidth / circuitGrid.ColumnDefinitions.Count - Line24.Width) / 2, HandModeWaySelector.Height / 2, (screenWidth / circuitGrid.ColumnDefinitions.Count - Line24.Width) / 2, (screenHeight / circuitGrid.RowDefinitions.Count) / 2);
    Line21.Margin = new Thickness((screenWidth / circuitGrid.ColumnDefinitions.Count - Line24.Width) / 2, 0, (screenWidth / circuitGrid.ColumnDefinitions.Count - Line24.Width) / 2, (screenHeight / circuitGrid.RowDefinitions.Count) / 2 - Line20.Height / 2);
    Line15.Margin = new Thickness(0, (HandModeWaySelector.Height / 2 - Line15.Height) / 2, 0, screenHeight / circuitGrid.RowDefinitions.Count - (HandModeWaySelector.Height - Line15.Height / 2));
    Line16.Margin = Line15.Margin;
    Line17.Margin = new Thickness((screenWidth / circuitGrid.ColumnDefinitions.Count) / 2, (HandModeWaySelector.Height / 2 - Line15.Height) / 2, 0, screenHeight / circuitGrid.RowDefinitions.Count - (HandModeWaySelector.Height - Line15.Height / 2));

}

person matthiasrathgeber    schedule 22.02.2018    source источник


Ответы (2)


Вы не должны полагаться на какие-либо меры, пока не будет выполнен (и стабилен) «процесс измерения». Попробуйте переместить вызов initCircuit внутрь обработчика MainPage Loaded. Вы должны получить какой-то результат.

РЕДАКТИРОВАТЬ: лучший подход:

    public MainPage()
    {
        this.InitializeComponent();
        this.circuitGrid.SizeChanged += circuitGrid_SizeChanged;
    }

    private void circuitGrid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        //check for valid size
        //if (valid) {
        //  initCircuit()
        //}
    }

    private void initCircuit()
    {
        //
    }

Идея состоит в том, чтобы «слушать» каждое изменение размера сетки, а затем оценивать, рисовать или нет. Проверка выполняется прямо для проверки NaN или чего-то числового. Я рекомендую выполнить быстрый тест в качестве проверки, прежде чем делать конкретный initCircuit. Это потому, что вы можете увидеть плотную последовательность вызовов SizeChanged во время начального процесса рендеринга. Не пуленепробиваемое решение, но на этом этапе вы должны увидеть, как все начинает работать.

person Mario Vernari    schedule 22.02.2018
comment
Здравствуйте, Марио, спасибо за ваш ответ. Я пробовал это, но безуспешно. Я также пытался вызывать initCircuit в некоторых других обработчиках Loaded, но и это было безуспешно. У вас есть другая идея? - person matthiasrathgeber; 22.02.2018
comment
ну, подсказка Loaded была скорее простой попыткой, чем реальным решением. Я отредактирую ответ для лучшего подхода. - person Mario Vernari; 22.02.2018
comment
ну теперь у меня получается как минимум такой же размер как и дисплей (800*480). Но сетка должна быть как раз под PivotHeaders (что занимает 10%: выяснено экспериментально), а значит должна иметь размер 800*432. Теперь сетка будет располагаться на 48 пикселей ниже нижней границы. - person matthiasrathgeber; 22.02.2018
comment
Хорошо, но где в вашем коде PivotHeaders? попробуйте добавить их, и вы должны увидеть, что ожидается. - person Mario Vernari; 23.02.2018
comment
Я добавил их в файл XAML. Разве этого недостаточно? Или мне нужно создать экземпляр заголовка, чтобы использовать его? Я очень новичок в программировании UWP с помощью С#. - person matthiasrathgeber; 23.02.2018

Из предоставленного вами кода позиции строк рассчитываются из screenSize, который является размером представления текущего приложения. Результат GetForCurrentView — это физическое разрешение экрана (обратите внимание, что это не разрешение экрана). Я думаю, что позиции должны рассчитываться из circuitGrid.Пожалуйста обратитесь к следующему коду:

private void initCircuit()
{
    ...

    double screenWidth = circuitGridSize.Width;
    double screenHeight = circuitGridSize.Height;

    ...
}

Кроме того, высота Pivot зафиксирована как 769, это повлияет на адаптивность позиций. Лучше, если он настроен на вертикальное заполнение StackPanel.

person Michael Xu - MSFT    schedule 23.02.2018