Is there any means to initialize "offline" binding for elements I've created in code through .baml/xaml parsing or imperative
What if I've <ViewBox/> with some resources+binded elements-all self contained but I created it from "sratch" and it's not displayed on screen.Now I want to simulate "complete" cycle of rendering to get RenderTargetBitmap of my ViewBox...well you get idea![]()
All work nice except {Binding} markup expressions dosen't get called.So,how I can "invoke" expression engine to make binding work.
I tried:
vb.Measure(new Size(1000,1000));
vb.Arrange(new Rect(vb.DesiredSize));
vb.UpdateLayout();
without luck from console app,have I forgot something
Thanks.

Offline binding
doakwolf
OK, we have:
<graph1 project>
Window1.xaml.cs:
namespace graph1 {
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1:Window {
///...
public void RenderBitmap() {
vb.Measure(new Size(1000, 1000));
vb.Arrange(new Rect(vb.DesiredSize));
vb.UpdateLayout();
RenderTargetBitmap rtb = new RenderTargetBitmap(Convert.ToInt32(vb.DesiredSize.Width), Convert.ToInt32(vb.DesiredSize.Height), 0, 0, new PixelFormat());
rtb.Render(vb);
JpegBitmapEncoder png = new JpegBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (FileStream fs = new FileStream("aaa.jpg", FileMode.Create)) {
png.Save(fs);
}
}
///…
public class MyConverter : IValueConverter, IMultiValueConverter
{
public object Convert(
object o,
Type type,
object parameter,
System.Globalization.CultureInfo culture) {
if (type == typeof(PointCollection)) {
PointCollection pc = new PointCollection();
XmlElement el = (XmlElement)o;
XmlElement doc = el.OwnerDocument.DocumentElement;
double y_max = double.Parse(doc.GetAttribute("Y_MAX")),
x_step = 1.75 * y_max / double.Parse(doc.GetAttribute("X_MAX"));
pc.Add(new Point(0, y_max));
foreach (XmlElement p in el.SelectNodes("Point")) {
Debug.WriteLine(p.GetAttribute("XX") + " " + p.GetAttribute("YY"));
Point pv = new Point(double.Parse(p.GetAttribute("XX")) * x_step, y_max - double.Parse(p.GetAttribute("YY")));
pc.Add(pv);
}
return pc;
}
else {
if (o is XmlAttribute) {
XmlAttribute a = (XmlAttribute)o;
double _max = double.Parse(a.OwnerElement.Attributes["Y_MAX"].Value);
if (a.Name == "X_MAX") _max = 1.75 * _max;
return _max;
}
else {
return 38492520.04 / 100;
}
}
}
public object ConvertBack(object o, Type type,object parameter,System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType,object parameter,System.Globalization.CultureInfo culture) {
double[] w = Array.ConvertAll<object, double>(values, delegate(object o) { return 0.1; });
return 100000d;
}
public object[] ConvertBack(object value, Type[] targetTypes,object parameter,System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
#endregion
}
}
Window1.xaml:
<Window x:Class="graph1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:graph1"
Title="graph1" Loaded="hh">
<Window.Resources>
<Style x:Key="Title" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="22"/>
</Style>
</Window.Resources>
<StackPanel>
<Viewbox x:Name="vb">
<Viewbox.Resources>
<c:MyConverter x:Key="l_c"/>
<XmlDataProvider x:Key="line" XPath="doc">
<x:XData>
<doc xmlns="" Y_MAX="38492520.04" X_MAX="10">
<Line NAME="aaa" COLOR="Blue">
<Point X_VALUE="26.09.05" XX="1" YY="15421199.2"/>
<Point X_VALUE="27.09.05" XX="2" YY="15730949.79"/>
</Line>
<Line NAME="bbb" COLOR="Red">
<Point X_VALUE="26.09.05" XX="1" YY="349889.81"/>
<Point X_VALUE="27.09.05" XX="2" YY="1557119.47"/>
</Line>
</doc>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="LineG">
<Polyline
Stroke="{Binding XPath=@COLOR}"
StrokeThickness="100000"
Points="{Binding Mode=OneTime,Converter={StaticResource l_c}}"/>
</DataTemplate>
</Viewbox.Resources>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="100000" ScaleY="100000"/>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel VerticalAlignment="Bottom">
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="0,100,0,0"/>
</Style>
</StackPanel.Resources>
<TextBlock>aaaaaaaaaaa</TextBlock>
<TextBlock>aaaaaaaaaaa</TextBlock>
<TextBlock>aaaaaaaaaaa</TextBlock>
</StackPanel>
<Border Grid.Column="1"
BorderBrush="Green"
DataContext="{StaticResource line}"
BorderThickness="100000,0,0,100000">
<ItemsControl x:Name="zz1" ItemsSource="{Binding XPath=*}" ItemTemplate="{StaticResource LineG}">
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Canvas
IsItemsHost="True"
Width="{Binding Path=Attributes[X_MAX],Mode=OneTime,Converter={StaticResource l_c}}"
Height="{Binding Path=Attributes[Y_MAX],Mode=OneTime,Converter={StaticResource l_c}}"/>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</Border>
<StackPanel Grid.Column="1" Grid.Row="1"
HorizontalAlignment="Left"
Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="45"/>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<TextBlock>aaaaaaaaaaa1</TextBlock>
<TextBlock>aaaaaaaaaaa2</TextBlock>
<TextBlock>aaaaaaaaaaa3</TextBlock>
</StackPanel>
</Grid>
</Viewbox>
</StackPanel>
</Window>
//================================================================================
Next,put following files in “debug” output directory of this project(workaround for .baml loading-to simulate window loading cycle):
a.cs:
using System.Windows;
using System;
class a
{
[System.STAThreadAttribute]
static void Main() {
graph1.Window1 w = new graph1.Window1();
w.RenderBitmap(true);//this will render “aaa.jpg”
System.Console.ReadLine();
}
}
a.cmd:
copy %PATH_TO_GRAPH1_PROJECT%\obj\Debug\graph1.g.resources a.g.resources
csc /res:a.g.resources /r:PresentationFramework.dll,PresentationCore.dll,WindowsBase.dll,UIAutomationProvider.dll,graph1.exe a.cs
//=======================================
and run a.cmd(after building graph1;-),you’ll get a.exe-console application that creates Window1 object and execute RenderBitmap method.Ofcourse,you can run graph1 project itself and see the difference(just add Loaded handler,for example which invoke RenderBitmap).
That’s all.
Run a.exe,in result we have “aaa.jpg” without binding…
Thank you.
P.S. By the way,"Loaded" for ViewBox or Window is never called in "offline/cosole" mode but it render static content anyway though binding engine is not working.Who responsible to raise "Loaded" event
mh433493
Look at previous post-it's simple console app,I tried:
graph1.
Window1 w= new graph1.Window1();w.Dispatcher.BeginInvoke(
DispatcherPriority.Background, new DispatcherOperationCallback( delegate(object o){
w.RenderBitmap(
true); return null;}
));
as you suggest-no luck,app just wait indefinitely.
Thanks.
Carlos Guzm&#225;n &#193;lvarez
I'm not 100% sure, but my gut tells me what you're trying to do isn't possible with WPF.
I'll need to find an expert on this, though.
Raptor0001
Could you give me a bit more context.
You're creating a ViewBox in code How are you adding it to the tree What is it's parent
SteveS_MS
Ah, you need an Application running.
No Application, no dispatcher...at least I'm pretty sure. (Need to chat with the experts...)
Regardless, I'm pretty sure you won't get an Image for the Window if you don't show the Window...otherwise Measure/Arrange/Render won't be called.
Joe Brinkman
TimSpencer
I'm not adding it to the tree and application event pulling cycle is not started-Application.Run(); is never invoked,so dispatcher thread is out of work;-)
All I do is deserialize ViewBox object from .xaml file using parser and tried to render it to .jpg using supplied code(no parent here)-it's simple console application,hence term "offline".
Thanks.
Martha Wieczorek
What code calls "RenderBitmap"
You may need to do a Dispatcher.BeginInvoke at Background priority to allow all of the bindings to update before you try to capture the image.
Have you used the dispatcher before
chrisexv6
So,what you think I've missed something
Best wishes.
ronnotel
I can assure you that ViewBox(background image,coordinate lines-static XAML content,I can call Measure/Arrange methods manually,but I can't call Bind() as in asp.net
) rendered perfectly well,but all dynamic functionality is turned off.I agree Application may be required but how I can do Application.Run()-start message processing cycle in non interactive environment-that's the question(for example in asp.net context or console app).
Thanks.
Bhargavi
pant
As I can understand,it dosen't matter where,if you have {} expressions or "Binding" objects itself.
I tried:
vb.Measure(new Size(1000,1000));
vb.Arrange(new Rect(vb.DesiredSize));
vb.UpdateLayout();
RenderTargetBitmap rtb=new RenderTargetBitmap(Convert.ToInt32(vb.DesiredSize.Width),Convert.ToInt32(vb.DesiredSize.Height),0,0,new PixelFormat());
rtb.Render(vb);// this dosen't respect {Binding} for Height and other properties
//binding simply not work IF vb (ViewBox) is created offline-is not displayed on screen(not inserted in visual tree),but created in imperative code(or loaded from .xaml file,it dosen't matter)
JpegBitmapEncoder png=new JpegBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using(FileStream fs=new FileStream("aaa.jpg",FileMode.Create)) {
png.Save(fs);
}
because of that "aaa.jpg" is empty-most of the logical tree of vb binded to some datasource(defined in vb context),particularly measurement properties of objects.So,you have nothing if you not displaying it on screen.
Regards.
drajurs
OK,I'll prepare code and put it here.
Thank you.
ralphg
Maybe some kind of mini bootstrap for Avalon subsystem exist without dispatcher participation By the way,if you're not using any expressions(binding included)-only pure static file(all props predefined in tree),all work as expected.
Regards.