WPF analogy for 'em' unit

2019-01-25 13:24发布

What is the WPF analogy for the CSS em unit?

5条回答
再贱就再见
2楼-- · 2019-01-25 13:26

Unfortunately, there is no equivalent in WPF of the em unit. All your font sizes, etc are always set in Pixels.

查看更多
SAY GOODBYE
3楼-- · 2019-01-25 13:27

Here is what I did. Created a MarkupExtension that converts Font size to EM based on font assigned on Window.

I would like to thank http://10rem.net/blog/2011/03/09/creating-a-custom-markup-extension-in-wpf-and-soon-silverlight

and

http://tomlev2.wordpress.com/tag/markup-extension/

for providing required knowledge.

[MarkupExtensionReturnType(typeof(double))]
public class EmFontSize : MarkupExtension
{
    public EmFontSize() { }

    public EmFontSize(double size)
    {
        Size = size;
    }

    [ConstructorArgument("size")]
    public double Size { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (serviceProvider == null)
            return null;

        // get the target of the extension from the IServiceProvider interface
        IProvideValueTarget ipvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        if (ipvt.TargetObject.GetType().FullName == "System.Windows.SharedDp")
            return this;

        DependencyObject targetObject = ipvt.TargetObject as DependencyObject;

        var window = TryFindParent<Window>(targetObject);
        if (window != null)
        {
            return window.FontSize * Size;
        }
        return 12 * Size;
    }

    public static T TryFindParent<T>(DependencyObject child) where T : DependencyObject
    {
        //get parent item
        DependencyObject parentObject = GetParentObject(child);

        //we've reached the end of the tree
        if (parentObject == null) return null;

        //check if the parent matches the type we're looking for
        T parent = parentObject as T;
        if (parent != null)
        {
            return parent;
        }
        else
        {
            //use recursion to proceed with next level
            return TryFindParent<T>(parentObject);
        }
    }

    public static DependencyObject GetParentObject(DependencyObject child)
    {
        if (child == null) return null;

        //handle content elements separately
        ContentElement contentElement = child as ContentElement;
        if (contentElement != null)
        {
            DependencyObject parent = ContentOperations.GetParent(contentElement);
            if (parent != null) return parent;

            FrameworkContentElement fce = contentElement as FrameworkContentElement;
            return fce != null ? fce.Parent : null;
        }

        //also try searching for parent in framework elements (such as DockPanel, etc)
        FrameworkElement frameworkElement = child as FrameworkElement;
        if (frameworkElement != null)
        {
            DependencyObject parent = frameworkElement.Parent;
            if (parent != null) return parent;
        }

        //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
        return VisualTreeHelper.GetParent(child);
    }
}

Sample Usage

xmlns:my="clr-namespace:FontSizeExample"
<TextBlock Text="Sample Font" FontSize="{my:EmFontSize 1.1}"/>
<TextBlock Text="Sample Font" FontSize="{my:EmFontSize .9}"/>
查看更多
啃猪蹄的小仙女
4楼-- · 2019-01-25 13:27

em size is the width of the uppercase letter M in the current font, there is no font-dependent sizing method in Wpf

Btw, WPF uses "device independent pixels" that are always 1/96 of an inch (because that's one pixels on today's monitors) so:

  • 1 pixel is 1/96 inches
  • 96 pixels in an inch
  • 1.33333 pixels is a point
  • 3.779 pixels is a mm

Those are extremely inaccurate on monitors because almost all monitors report a 96DPI resolution and ignore the real pixel size, but are very useful when printing.

查看更多
贪生不怕死
5楼-- · 2019-01-25 13:37

AFAIK, there isn't one right now. But you can make your desire for this known here.

One alternative (and I don't know if this is possible either) would be to measure how big the desired font is, then take that as your "ems" unit, then scale using those "units" instead.

查看更多
放荡不羁爱自由
6楼-- · 2019-01-25 13:43
<ScaleTransform ScaleX="1.2" ScaleY="1.2"></ScaleTransform> 

seems to be more or less the 1.2em alternative.

查看更多
登录 后发表回答