2011-04-27 35 views
1

我想在c#中開始使用WPF。 我將Canvas設置爲一個窗口的內容,然後創建另一個Canvas並將其作爲第一個Canvas的子項(與其他元素(如按鈕和標籤)一起)。一切都正常運行,直到我創建一個圖像對象和動態地添加它到內畫布:在WPF中的圖像控制奇怪的行爲

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是內畫布。圖像的來源是一個PNG文件,從XML文件中提取(返回的字符串是正確的)。

奇數行爲是在這裏:如果我註釋掉線

double d = m_Img.Source.Width; 

不再被顯示圖像,雖然在畫布其他控件(如標籤和按鈕)的正確顯示。

我不需要源圖像的寬度,所以編譯器告訴我該變量永遠不會被使用。

我將Visual Studio 2010更新爲最後一個SP1,但行爲依然存在。谷歌也沒有幫助。我開始認爲Width屬性可能有一個getter方法觸發某個動作,但不能解決這個難題。


編輯:使用源的另一個屬性(例如高度)會發生同樣的事情。如果我訪問至少一個屬性,則圖像顯示正常。

回答

0

不要通過代碼定義自己的觀點 - 使用XAML,
即使你想創建動態的觀點,使用XAML是更乾淨
並使用一個好的設計師的應用程序(如混合),你會注意你沒有考慮的事情。

有些事情你沒有考慮的是.Width不必等於.ActalWidth。
默認寬度通常是double.NaN(意思是自動寬度)。

使用綁定,將A的寬度綁定到B的寬度,使用邊距,填充或值轉換器將寬度A綁定到B的寬度const。

使用佈局面板(例如Grid,StackPanel,DockPanel)可以簡化多個控件的對齊(並且無綁定)。

此外,更喜歡使用standard naming conventions(例如,沒有m_)。

+0

我不能使用其他佈局面板,因爲我需要一個相當奇怪的佈局,但我一定會考慮綁定和代碼和視圖之間更強的分離..我實際上試圖在XAML中做到這一點(和它工作),但我堅持通過代碼來做到這一點,並想知道爲什麼它不起作用。不過謝謝你的建議。 – DrWatson 2011-04-27 20:38:02

1

我終於發現會發生什麼:Image控件需要將Source的屬性DecodePixelWidth和DecodePixelHeight設置爲正確的值。

一旦創建了源,這些值不會被設置,並且圖像不會被繪製。在第一次訪問作爲源的BitmapImage的任何屬性時,圖像被實際解碼,並且這些屬性被設置爲解碼圖像的最終寬度和高度(因此可以繪製圖像)。

我可以這樣

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; 

設置用手這些值(用強制轉換爲int)解決這一點,但我想我會重新設計我有更好的分離意見(意見XAML,模型和通過代碼觀看模型)。

該位在第二個音符在http://msdn.microsoft.com/en-us/library/ms747027.aspx

當你用指定寬度或高度圖像的尺寸也提到了,你也應該設置DecodePixelWidth或DecodePixelHeight相同的各尺寸。