Getting WPF Control Template in IronPython
I always find myself needing a control template so I can customize one of the WPF controls. I used to fire up Expression Blend to get it, and then realized I could write a little IronPython code to do it. Paste this code into the IronPython 2.0 or 2.6 console to see it work!
import clr clr.AddReference("System.Xml") clr.AddReference("PresentationFramework") from System.Windows import Window from System.Windows.Controls import * from System.Windows.Markup import XamlWriter from System.Xml import XmlWriter, XmlWriterSettings from System.Text import StringBuilder # Need to render the control on screen so it will have a Control Template def getControlTemplate(ctl): "Gets the control template for a WPF control" window = Window() window.Content = ctl window.Show() window.Close() return ctl.Template settings = XmlWriterSettings() settings.Indent = True settings.IndentChars = " " sb = StringBuilder() writer = XmlWriter.Create(sb,settings) ### replace Button() with an instance of whatever control you want. ### XamlWriter.Save(getControlTemplate(Button()), writer) print (sb.ToString())
Reference to Self in XAML
I’m always finding that I need to get a reference to the root element (this) in my XAML markup. If I’m in a situation that I can use a Binding, I can do something like this where I’m getting the Height of the current Window):
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Height}
However, there are many times that I need a reference to the root where I can’t use a binding. I really, really hope somebody will prove me wrong and show me there is a better way to do this that’s already built in to WPF, but since I haven’t been able to find anything, I added a MarkupExtension that uses reflection to get a reference to the private fields serviceProvider._Context._rootElement:
public class SelfExtension : MarkupExtension { public override object ProvideValue(IServiceProvider serviceProvider) { object self = null; Type selfType = serviceProvider.GetType(); FieldInfo contextFieldInfo = selfType.GetField("_context", BindingFlags.NonPublic | BindingFlags.Instance); if(contextFieldInfo != null) { object context = contextFieldInfo.GetValue(serviceProvider); Type contextType = context.GetType(); FieldInfo rootElementFieldInfo = contextType.GetField("_rootElement", BindingFlags.NonPublic | BindingFlags.Instance); if(rootElementFieldInfo != null) self = rootElementFieldInfo.GetValue(context); } return self; } }Yes, this is a terrible hack using reflection to access private fields, and there’s a good chance it will go away in a future version of WPF…hopefully because Microsoft builds in their own extension to do this properly. If you know of a better way, please speak up!
[Update: Microsoft addressed this is .NET 4]
Here is a new version that doesn’t require reflection using the updated API in .NET 4:
public class SelfExtension : MarkupExtension { public override object ProvideValue(IServiceProvider serviceProvider) { return ((System.Xaml.IRootObjectProvider)serviceProvider).RootObject; } }
Loading an Object from XAML Markup
I’ve got to say that my absolute favorite feature of WPF is that you can create your entire user interface in a string of XAML.
Read on at https://loosexaml.wordpress.com/loading-ui-from-markup/
Using Reflection in WPF
Reflection is a very powerful tool for building code that is highly customizable at runtime, making it very reusable. If you’re going to make an application that is primarily loose XAML, you will want to make whatever code you do write as flexible as possible, and to do so, it helps to have a firm grasp of reflection.
Read on at https://loosexaml.wordpress.com/reflection-for-wpf-rockstars/