我正在整理原型以使用XAML创建PNG按钮。基本的想法是,可以从本地化的字符串生成漂亮的渐变图像按钮,而不是由任何类型的图形部门创建它们。
我发现的最直接的例子是构建一个C#程序集和call it from PHP。我将它转换为纯C#。这是我的基本工作原型的样子。
XAML文件如下所示:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Button HorizontalAlignment="Left" VerticalAlignment="Top" Content="Add To Cart" FontFamily="Arial" FontSize="11" Height="24" FontWeight="Bold" Margin="0,3,0,0">
<Button.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF3F3F3" Offset="0"/>
<GradientStop Color="#FFEBEBEB" Offset="0.5"/>
<GradientStop Color="#FFDDDDDD" Offset="0.502"/>
<GradientStop Color="#FFCDCDCD" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>
</Grid>
Program.cs看起来像:
class Program
{
static void Main(string[] args)
{
FileInfo xamlFile = new FileInfo("Button.xaml");
var inputXaml = File.ReadAllText(xamlFile.FullName);
Thread pngCreationThread = new Thread((ThreadStart) delegate()
{
GenImageFromXaml(inputXaml);
});
pngCreationThread.IsBackground = true;
pngCreationThread.SetApartmentState(ApartmentState.STA);
pngCreationThread.Start();
pngCreationThread.Join();
}
public static void GenImageFromXaml(string xaml)
{
var element = (FrameworkElement)XamlReader.Parse(xaml);
var pngBytes = GetPngImage(element);
using(BinaryWriter binWriter =
new BinaryWriter(File.Open(@"output.png", FileMode.Create)))
{
binWriter.Write(pngBytes);
}
}
private static byte[] GetPngImage(FrameworkElement element)
{
var size = new Size(element.Width, element.Height);
element.Measure(size);
element.Arrange(new Rect(size));
var renderTarget =
new RenderTargetBitmap((int)element.RenderSize.Width,
(int)element.RenderSize.Height,
96, 96,
PixelFormats.Pbgra32);
var sourceBrush = new VisualBrush(element);
var drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawRectangle(
sourceBrush, null, new Rect(
new Point(0, 0),
new Point(element.RenderSize.Width,
element.RenderSize.Height)));
}
renderTarget.Render(drawingVisual);
var pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
using (var outputStream = new MemoryStream())
{
pngEncoder.Save(outputStream);
return outputStream.ToArray();
}
}
}
我想要的是可以用作模板的XAML文件,并且交换按钮中的实际字符串。我的原型在基本级别上工作,从输入的XAML文件中渲染出一个图像。
但是,XAML文件明确指定高度和宽度。由于宽度不会事先知道而且任何字体修改都会混淆,因此按钮本身的字符串动态提供是一个问题。
我正在寻找的是一种在运行时计算高度和宽度的方法,或者根据文本字符串预先计算它们的简单方法。有什么想法吗?
答案 0 :(得分:2)
您可以尝试下面的
1不要在xaml中设置宽度和高度
2替换您测量/安排来电:
var size = new Size(double.PositiveInfinity , double.PositiveInfinity );
element.Measure(size);
element.Arrange(new Rect(element.DesiredSize));
Measure根据您传递的大小设置DesiredSize属性,这可能是您希望它的大小。
3(不确定是否需要)将Grid(LayoutRoot)设置为Top / Left对齐,因为Grid希望默认采用所有可用的大小,你不希望这样。