2009-08-24 72 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