What is the WPF analogy for the CSS em unit?
问题:
回答1:
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.
回答2:
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}"/>
回答3:
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.
回答4:
<ScaleTransform ScaleX="1.2" ScaleY="1.2"></ScaleTransform>
seems to be more or less the 1.2em alternative.
回答5:
Unfortunately, there is no equivalent in WPF of the em unit. All your font sizes, etc are always set in Pixels.