2009-08-24 74 views
2

我需要在WPF呈現它之前計算可視元素的邏輯寬度。我如何計算WPF視覺元素的邏輯寬度?

爲了便於說明,我會說這個視覺元素可能是一個Polygon對象。它可能是其他的東西,但多邊形可以很容易地形象化。

所以XAML可能看起來是這樣的:

<Window x:Class="MyCLRNamespace.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
</Window> 

和代碼隱藏看起來是這樣的:

namespace MyCLRNamespace 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      //This is the visual element in question. It's a simple triangle. 
      Polygon MyPolygon = new Polygon(); 
      MyPolygon.Points = new PointCollection { new Point(100, 0), 
                 new Point(200, 200), 
                 new Point(0, 200) }; 
      double PolyWidth = MyPolygon.Width; 
      /* In this case, PolyWidth will be set to double.NaN, since 
       MyPolygon.Width is never set. 

       I need to be able to calculate the logical width of an element, 
       unrelated to the WPF rendering system. This means that I can't 
       rely on FrameworkElement.ActualWidth to calculate the width for 
       me. I need to be able to look at the MyPolygon object (or its 
       content) and figure out that it is set to a visual element that 
       should be 200dips wide before any parent element applies any 
       operations to it - regardless of what MyPolygon.Width may or may 
       not be set to. 

       It should also be noted that I don't have to rely on 
       FrameorkElement. If there are more generic alternatives, such as 
       the UIElement or Visual classes, I'd prefer to use those instead 
       of the more specific FrameworkElement. The more robust I can make 
       this, the better. */ 
     } 
    } 
} 

回答

10

System.Windows.UIElement類提供了用於在任何父子元素關係之外度量自身的方法。

在您嘗試使用測量值之前,檢查IsMeasureValid是至關重要的。如果IsMeasureValid爲false,則需要手動調用UIElement.Measure()方法以確保您具有最新的度量元素及其內容。如果IsMeasureValid爲真,那麼再次測量就不會受傷。它會覆蓋之前存儲的所有測量結果。

如果您想要在沒有外部限制的情況下對元素進行穩定測量,請將無限大小作爲UIElement.Measure()方法的availableSize參數。

UIElement.Measure()方法將在UIElement.DesiredSize屬性中存儲元素的測量大小。我不相信這會對WPF呈現系統產生任何負面影響,因爲任何父元素都會保證在呈現它之前用它自己的可用大小約束重新測量元素。這可能會影響屏幕上元素的最終尺寸,但在應用父子約束之前,它不會影響元素的原始所需尺寸。

namespace MyCLRNamespace 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      Polygon MyPolygon = new Polygon(); 
      MyPolygon.Points = new PointCollection { new Point(100, 0), 
                 new Point(200, 200), 
                 new Point(0, 200) }; 
      //if (MyPolygon.IsMeasureValid == false) 
       MyPolygon.Measure(new Size(double.PositiveInfinity, 
              double.PositiveInfinity)); 

      double PolyWidth = MyPolygon.DesiredSize.Width; 
     } 
    } 
} 
+0

如果在調用度量後得到0,0,則可以將容器元素直接放在可視樹中的元素上方並測量該元素。也許不是最好的解決方案,但是如果你絕望的話,它是有效的。 – 2016-10-06 18:27:25

0

唉,我們再次見面。如果你更多地告訴我們你想要達到的目標,這也許會有所幫助。 WPF實際上使用獨立於設備的單元爲它的尺寸,而這正是ActualWidth的是(從MSDN):

元素的寬度,如在與設備無關的單元(每單位1 /第96英寸)的值。默認值是0(零)。

如果您看到可用性古怪的ActualWidth的值你可能要聽SizeChanged事件或覆蓋OnRenderSizeChanged。我認爲兩者有微妙的差異,但我不確定這些差異是什麼。

+0

我傾向於在代碼註釋中做大部分解釋。也許我不應該這樣做......無論如何,ActualWidth只有在你需要渲染寬度的東西時纔有用。我想要的邏輯寬度。我想要的值是XAML中多邊形聲明的「200」值。 ActualWidth不能保證等於元素的聲明寬度,在這種情況下,我甚至不設置調節器寬度屬性。但是,如果沒有其他因素存在,多邊形實際上將會變寬200倍。這是我需要我的程序能夠動態計算的價值。 – Giffyguy 2009-08-24 02:05:42

+0

對,那麼在什麼情況下ActualWidth不是200?唯一不是這樣的情況,恕我直言,當它的父母以某種方式剪輯它。您是否嘗試過調試代碼以詢問ActualWidth的值? – 2009-08-24 04:13:39

+0

在多邊形尚未渲染的情況下。我想製作一個這種場景的代碼示例,但我想不到任何好的方式來顯示它,而不發佈我的整個項目。這太混亂了。 – Giffyguy 2009-08-24 04:19:15