WPF中图像控制的奇怪行为
本文关键字:图像 控制 WPF | 更新日期: 2023-09-27 17:53:57
我正在尝试用c#开始使用WPF。我将Canvas设置为窗口的内容,然后创建另一个Canvas并将其作为第一个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是内部画布。图像的来源是从XML文件中提取的PNG文件(返回的字符串是正确的)。
奇怪的行为在这里:如果我注释掉
行double d = m_Img.Source.Width;
图像不再显示,尽管画布中的其他控件(如标签和按钮)被正确显示。
我不需要源图像的宽度,所以编译器告诉我这个变量永远不会被使用。
我将Visual Studio 2010更新到最后一个SP1,但行为仍然存在。谷歌也帮不上忙。我开始认为Width属性可能有一个getter方法来触发一些动作,但不能解决这个难题。
编辑:同样的事情发生使用源的另一个属性(例如高度)。如果我访问了至少一个属性,图像显示ok
我终于发现发生了什么:图像控件需要将源的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设置为相同的大小。
不要通过代码定义视图-使用XAML,
即使你试图创建动态视图,使用XAML也要干净得多
使用一个好的设计应用程序(例如Blend),你会注意到你没有考虑到的事情。
你没有考虑到的一些事情是。width不一定等于。actalwidth。
默认宽度通常是两倍。NaN(意思是自动宽度).
使用绑定,将宽度A绑定到宽度B,使用边距,填充或值转换器将宽度A绑定到宽度B - const。
使用布局面板(例如Grid, StackPanel, DockPanel)使多个控件的对齐变得简单(并且没有绑定)。
另外,最好使用标准的命名约定(例如没有m_)。