Поделиться через


Layout Rounding

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Layout rounding is a concept in Silverlight whereby the Silverlight layout system rounds off any non-integral values that exist at the time of the layout render pass. Layout rounding has an API surface area of just a single API, UIElement.UseLayoutRounding, but the default layout rounding behavior that is built in to the layout system has implications for the visual appearance of your application. It also has implications for how you might set your property values or use existing values of layout properties if you are performing some of your own layout logic in a custom panel or other class.

The UseLayoutRounding Property

The immediate API surface for layout rounding behavior is the single property UIElement.UseLayoutRounding. The default value of this property is true, which means that layout rounding is on by default.

Layout Rounding and Subpixel Rendering

The intention of layout rounding is to prevent subpixel rendering logic from producing antialiasing effects that generally are regarded as a poor visual presentation. One of the most extreme examples of this would be if you had a single-pixel straight black line on exactly a half-pixel boundary of the pixel grid. Subpixel rendering would average the pixels on either side of the .5 division. Instead of a single-pixel line of 100% black, it would render a 2-pixel wide line of 50% gray.

Under layout rounding, such a line would go through layout and be aligned to the nearest whole pixel in the grid, and both the small width and the intended 100% black information is preserved.

Layout Rounding and Non-Integral Values Specified for Properties

There are quite a few properties in Silverlight that specify the dimensions of an object in terms of a height or width. All of these properties can take a Double value as the property type, which means that the values you provide could be non-integral. However, if you are not deliberately setting UseLayoutRounding as false, there is no reason to use a non-integral value for these property values. Properties where you might set a non-integral value, such as FrameworkElement.Width, will faithfully report the non-integral value you set, but the layout system will ultimately round it to whole pixels for rendering purposes. Also, in most cases, the value of FrameworkElement.ActualWidth and FrameworkElement.ActualHeight reflect the influence of the layout system and the layout rounding behavior and report back the rounded value. Other factors might also calculate dimensions for objects in UI, such as the Star or Auto sizing modes for columns or rows of a Grid. Because this involves layout behavior of the Grid, FrameworkElement.ActualWidth and FrameworkElement.ActualHeight for determined values are also usually returned as rounded values.

NoteNote:

Double typing for the sizing properties in Silverlight is mostly for WPF compatibility. WPF supports a conversion behavior for other unit types, and also supports a device-independent pixel concept that has platform dependencies. Silverlight is cross-platform, and does not support the unit types; therefore, the conversion requirements that exist for WPF and require an underlying Double are seldom relevant in Silverlight programming.

ActualHeight and ActualWidth of TextBlock

Text and TextBlock are a general feature area where antialiasing is crucial for producing readable text particularly at smaller pixel sizes. The TextBlock class inherits the ActualWidth and ActualHeight from FrameworkElement. When exposed on TextBlock, these properties can provide a non-integral value and do not exhibit rounding behavior, if you check them on a TextBlock where you specified a Text string but not a Height or Width (which is the typical TextBlock usage).

If you are writing a panel, and are measuring and arranging TextBlock elements, you might want to round the ActualWidth and ActualHeight values for your own layout purposes. However, you might also deliberately not round those values depending on your class logic. For instance, you might be adding or otherwise calculating the values and might want exact values rather than possibly losing information through rounding.

Setting UseLayoutRounding to False

In general, it is expected that the layout rounding behavior will improve the visual appearance of UI versus what would be rendered if subpixel values were rendered into the pixels on either side. However, there might be situations or certain application scenarios where the subpixel rendering behavior is desirable instead. If you think you have such a scenario, you can set UIElement.UseLayoutRounding to false. If you do so, you should generally set the value on the root object, which will propagate the behavior to all child objects in the visual tree and layout.

NoteNote:

UseLayoutRounding exists on UIElement because generally it controls the behavior of classes that are layout containers, such as panels, but there are potentially layout containers that are not panels (any FrameworkElement could implement ArrangeOverride and the other layout APIs).