none
WPF: Определение размеров визуальных элементов управления при установке у них Height="Auto", VerticalAlignment="Stretch" RRS feed

  • Вопрос

  • Необходимо на форме разместить некоторое количество элементов управления, сделать их привязку, растяжение, т.е. организовать более-менее достойный GUI. Размещаю на форме элемент Image:

     

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Image Height="152" HorizontalAlignment="Left" Margin="100,27,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="251" />
        </Grid>
    </Window>
    

     

    Делаю нужные привязки, размещаю там же кнопку(button1):

     

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Image Height="Auto" HorizontalAlignment="Stretch" Margin="0,0,0,70" Name="image1" Stretch="Fill" VerticalAlignment="Stretch" Width="Auto" />
            <Button Content="Button" Height="32" HorizontalAlignment="Center" Margin="0,0,0,10" Name="button1" VerticalAlignment="Bottom" Width="105" Click="button1_Click" />
        </Grid>
    </Window>
    

     

    Запускаем: привязка отлично работает, визуально все как надо. Теперь в методе button1_Click необходимо получить высоту и ширину объекта image1. Не долго думая, просто пишем:

     

    Int32 currentImage1Height, currentImage1Width;        
    private
    void button1_Click(object sender, RoutedEventArgs e) { currentImage1Height = Convert.ToInt32(image1.Height); currentImage1Width = Convert.ToInt32(image1.Width); }

     

    Запускаем, нажимаем, а в ответ получаем OverflowException, т.к. image1.Height и image1.Width равны NaN(в XAML имеют значение "Auto"). Возможно без излишних исканий получить ширину и высоту объекта image1, вычисленную данным элементом при проходе измерения в процессе конструирования, но эта величина является константой и поэтому при изменении размера формы=>изменения текущего размера image1 никак изменяться не будет. Поле image1.RenderSize также мало толку дает.

    В элементарном Windows Forms выше написанный код спокойно работает(для объекта PictureBox), а в WPF...

    Хотелось бы узнать: возможно ли как-то вычислить размеры объекта Image при установлении свойств размера в значение "Auto", а привязки в "Stretch"?

     

     



    • Изменено Mixim33 25 октября 2011 г. 8:22
    25 октября 2011 г. 8:21

Ответы

  • Пока в image не загружена картинка, то его визуально как бы и не существует на форме и image не рендерится, поэтому и размер, возвращаемый свойствами равен 0. Для проверки можете подписаться на события клика по image:

            <Image Height="Auto" HorizontalAlignment="Stretch" Margin="0,0,0,70" Name="image1" 
                   Stretch="Fill" 
                   VerticalAlignment="Stretch" 
                   Width="Auto"
                   MouseDown="image1_MouseDown"
                   PreviewMouseDown="image1_MouseDown"
                   MouseLeftButtonDown="image1_MouseDown" 
                   PreviewMouseLeftButtonDown="image1_MouseDown"/>
    

    И обработчик:

            private void image1_MouseDown(object sender, MouseButtonEventArgs e)
            {
                MessageBox.Show("hello");
            }
    

    Пока картинка загружена не будет - событие отрабатывать не будет.

    Поэтому скорей всего вам придется как то исхищряться, например, либо задавать картинку размеров 1 на 1 пиксел белого цвета, либо вычислять размеры image исходя из размеров формы.


    Для связи [mail]
    • Помечено в качестве ответа Abolmasov Dmitry 28 октября 2011 г. 8:54
    25 октября 2011 г. 11:14

Все ответы

  • Используйте ActualWidth/ActualHeight.
    25 октября 2011 г. 10:05
    Отвечающий
  • Используйте ActualWidth/ActualHeight.

    Пытался и их использовать, но они также возвращают бред, в том то и проблема!

    Поясню: в XAML пишем вышеуказанный код, ставим точку остановки в методе button1_Click, запускаем программу, разворачиваем окно и проверяем чему равны данные свойства, получаем ответ: image1.ActualWidth=0 и image1.ActualHeight=0. Ладно, запускаем программу и не разворачиваем окно(вдруг данные свойства меняются каким-то "интересным и непостижимым" образом), итог: image1.ActualWidth=0 и image1.ActualHeight=0, т.е. ActualWidth/ActualHeight никак не меняются. Позволю себе предположить, что они будут показывать "нормальное" правильное значение, когда в image1 будет загружена некоторая картинка, но в таком случае поля Width и Height также отображают то, что нужно(проверял с помощью отладчика)!


    Неужели никак нельзя узнать размеры элемента Image, если установлены ранее указанные свойства и не загружена в него картинка?


    • Изменено Mixim33 25 октября 2011 г. 10:33
    25 октября 2011 г. 10:18
  • Пока в image не загружена картинка, то его визуально как бы и не существует на форме и image не рендерится, поэтому и размер, возвращаемый свойствами равен 0. Для проверки можете подписаться на события клика по image:

            <Image Height="Auto" HorizontalAlignment="Stretch" Margin="0,0,0,70" Name="image1" 
                   Stretch="Fill" 
                   VerticalAlignment="Stretch" 
                   Width="Auto"
                   MouseDown="image1_MouseDown"
                   PreviewMouseDown="image1_MouseDown"
                   MouseLeftButtonDown="image1_MouseDown" 
                   PreviewMouseLeftButtonDown="image1_MouseDown"/>
    

    И обработчик:

            private void image1_MouseDown(object sender, MouseButtonEventArgs e)
            {
                MessageBox.Show("hello");
            }
    

    Пока картинка загружена не будет - событие отрабатывать не будет.

    Поэтому скорей всего вам придется как то исхищряться, например, либо задавать картинку размеров 1 на 1 пиксел белого цвета, либо вычислять размеры image исходя из размеров формы.


    Для связи [mail]
    • Помечено в качестве ответа Abolmasov Dmitry 28 октября 2011 г. 8:54
    25 октября 2011 г. 11:14
  • Поэтому скорей всего вам придется как то исхищряться, например, либо задавать картинку размеров 1 на 1 пиксел белого цвета, либо вычислять размеры image исходя из размеров формы.
    Для связи [mail]

    Именно так я и думал, что придется несколько извращаться: задавать картинку размеров 1 на 1 пиксел. Однако, это же не совсем правильно(неправильно работает компонент Image).

    Кстати, ради интереса задал у кнопки(Button) значение Height равным "Auto", установил растяжение и посмотрел через отладчик чему в действительности равна высота данной кнопки - NaN. Ладно, возвращение такого значения для Image ещё хоть можно объяснить с точки зрения логики(странной, но все же), но "что надо загрузить в Button", чтобы высота стала нормальным значением?

    25 октября 2011 г. 21:34
  • Свойсвтва ActualHeight и ActualWidth нормально в этом случае показывают размеры кнопки.


    Для связи [mail]
    26 октября 2011 г. 5:49
  • Одну и туже функциональность можно реализовать по-разному. Расскажите чего вы хотите добиться, возможно мы сможем подсказать более красивое решение.
    26 октября 2011 г. 7:26
    Отвечающий