Bindings not applied to dynamically-loaded xaml
Asked Answered
S

1

8

I'm using XamlReader successfully to load a xaml file and create a FrameworkElement to work with.

The xaml I'm loading has binding expressions in it such as:

<TextBlock Text="{Binding DataContextTextProperty}" />

If I place the FrameworkElement I get back from XamlReader.Load() into a WPF window, the binding all works fine.

However, in this case I'm using Laurent Bugnion's excellent article on creating PNGs from WPF/XAML. Since the result of XamlReader.Load() is written directly to a PNG via a VisualBrush, it seems the necessary mechanics of WPF to invoke binding expressions are bypassed.

This leads me to believe that the actual bindings aren't really being invoked just by calling XamlReader.Load(), or that they're not working because of something I don't know about to do with there not being a visual tree until you add the FrameworkElement to an existing visual tree or something.

Is there something I can do to ensure these bindings are invoked?

Many thanks in advance.

Spavin answered 22/9, 2011 at 13:17 Comment(2)
I do think a layout and render pass is required for a View to be writeable as an image and that is possible only if we load it onto a visual tree. Correct me if I am wrong. Although XamlWriter with FlowDocument is a little different story .Lanugo
@AngelWPF I managed to solve it and have posted an answer below. It does seem to be behaving how I want, so providing there isn't some naive mistake I've made, I'm going to go with it. I can't tell you how relieved I am to get this working...Spavin
S
5

I FIXED IT!!

Ahem, allow me to explain...

I have no idea how I got to it now, but I found a helpful-sounding article on MSDN regarding Initialization for Objects Not in an Object Tree.

In it I found the following code example:

Button b = new Button();
b.BeginInit();
b.Background = Brushes.Blue;
b.Width = b.Height = 200;
b.EndInit();
b.Measure(paperSize);
b.Arrange(new Rect(paperSize));
b.UpdateLayout();

I looked at the (again, excellent) example from Laurent that I mentioned in the question above, and customised the use of XamlReader as follows:

var element = (FrameworkElement)XamlReader.Load(xamlInput);

element.BeginInit();
element.DataContext = dataContext;

...

element.Measure(renderingSize);
element.Arrange(renderingRectangle);

element.EndInit();
element.UpdateLayout();

I added the BeginInit(), EndInit() and UpdateLayout() (though by process of elimination I believe UpdateLayout() is the key) and now the binding expressions in my dynamically-loaded xaml are working correctly. Hurrah!

Spavin answered 22/9, 2011 at 13:48 Comment(2)
It's not clear what you weren't doing before. What's the key bit?Proserpina
Ahh yes in my excitement I forgot to make it clear. I've updated the answer now. :)Spavin

© 2022 - 2024 — McMap. All rights reserved.