我正在尝试在c#中开始使用WPF。 我将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;
虽然正确显示了画布中的其他控件(例如标签和按钮),但不再显示图像。
我不需要源图像的宽度,因此编译器告诉我从不使用变量。
我将Visual Studio 2010更新到最后一个SP1,但行为仍然存在。谷歌也没有帮助。我开始认为Width属性可能有一个触发某些动作的getter方法,但无法解决这个难题。
编辑:使用Source的另一个属性(例如Height)也会发生同样的事情。如果我访问至少一个属性,则图像显示正常。
答案 0 :(得分:1)
我终于发现了会发生什么:Image控件需要将Source的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设置为相同的相应大小。
答案 1 :(得分:0)
不要通过代码定义您的视图 - 使用XAML,
即使您正在尝试创建动态视图,使用XAML也要干净得多
并且使用一个好的设计师应用程序(例如Blend),你会注意到你没有考虑的事情。
你没有考虑的一些事情是.Width不一定等于.ActalWidth 默认宽度通常为double.NaN(表示自动宽度)。
使用绑定,将A的宽度绑定到B的宽度,使用边距,填充或值转换器使宽度A绑定到宽度为B - const。
使用布局面板(例如Grid,StackPanel,DockPanel)使多个控件的对齐变得简单(并且无绑定)。
此外,更喜欢使用standard naming conventions(例如,没有m _)。