Странное поведение управления изображениями в WPF - PullRequest
1 голос
/ 28 апреля 2011

Я пытаюсь начать работу с WPF в c #. Я устанавливаю Canvas в качестве содержимого окна, затем создаю другой Canvas и помещаю его как дочерний элемент первого Canvas (вместе с другими элементами, такими как кнопки и метки). Все работает нормально, пока я не создаю объект Image и не добавляю его динамически во внутренний Canvas:

Image m_Img = new Image
{
    Name = "img1",
    Width = cvWindow.Width,
    Height = dUsefulHeight,
    Stretch = Stretch.Uniform
};

m_Img.Source = new BitmapImage(
    new Uri(xMap.SelectSingleNode("@image").FirstChild.Value,
        UriKind.RelativeOrAbsolute));

Canvas.SetLeft(m_Img, 0);
Canvas.SetTop(m_Img, 0);

double d = m_Img.Source.Width;

cvWindow.Children.Add(m_Img);

Здесь m_Img - изображение, которое я создаю, cvWindow - внутренний Canvas. Источником изображения является файл PNG, извлеченный из файла XML (возвращенная строка верна).

Странное поведение здесь: если я закомментирую строку

double d = m_Img.Source.Width;

Изображение больше не отображается, хотя другие элементы управления в Canvas (например, надписи и кнопки) отображаются правильно.

Мне не нужна ширина исходного изображения, поэтому компилятор сообщает мне, что переменная никогда не используется.

Я обновил Visual Studio 2010 до последнего пакета обновления 1, но поведение осталось. Google тоже не помогает. Я пришел к выводу, что свойство Width может иметь метод получения, который запускает какое-то действие, но не может решить головоломку.


Редактировать: То же самое происходит с использованием другого свойства источника (например, Высота). Если я обращаюсь хотя бы к одному свойству, изображение отображается нормально.

Ответы [ 2 ]

1 голос
/ 28 апреля 2011

Я наконец обнаружил, что происходит: элемент управления Image требует, чтобы свойства DecodePixelWidth и DecodePixelHeight источника были установлены на правильные значения.

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

Я могурешить эту проблему, установив эти значения вручную (с приведением к int), например,

BitmapImage bs1 = new BitmapImage();
bs1.BeginInit();
bs1.UriSource = new Uri(
    xMap.SelectSingleNode("@image").FirstChild.Value,
    UriKind.RelativeOrAbsolute);
bs1.EndInit();
bs1.DecodePixelHeight = (int)bs1.Height;
bs1.DecodePixelWidth = (int)bs1.Width;

m_Img.Source = bs1;

, но я думаю, что я буду переделывать свои представления с лучшим разделением (представления в XAML, модели и модели представления через код).

Этот бит также упоминается во втором примечании в http://msdn.microsoft.com/en-us/library/ms747027.aspx

Когда вы указываете размер изображения с помощью ширины или высоты, вы также должны установить либо DecodePixelWidthили DecodePixelHeight для соответствующего размера.

0 голосов
/ 28 апреля 2011

Не определяйте ваши взгляды с помощью кода - используйте XAML,даже если вы пытаетесь создать динамические представления, использование XAML намного более чистои используя хорошее дизайнерское приложение (например, Blend), вы заметите вещи, которые вы не учли.

Некоторые вещи, которые вы не учли, заключаются в том, что .Width не обязательно равен .ActalWidth.Ширина по умолчанию обычно double.NaN (что означает автоматическую ширину).

Используйте привязки, привязайте ширину A к ширине B, используйте конвертеры полей, отступов или значений, чтобы сделать ширину A привязанной к ширине B -const.

Используйте панели макетов (например, Grid, StackPanel, DockPanel), чтобы упростить выравнивание нескольких элементов управления (и без привязки).

Кроме того, предпочитайте использовать стандартные соглашения об именах (например, нет м _).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...