0
votes

We're in the process of updating our gallery WPF application which contains our custom styled controls. The design is to have a toggle to show the XAML behind those custom controls, for easy reference and a guide for new colleagues.

The way I've currently implemented this is by creating two .xaml files, one containing just the controls, one with the controls and a textblock with the XAML coded used to implement those controls.

This is not something that's easily maintainable, since the quotes, >,< and other characters are not escaped in XAML strings. For reference this is what I have now in one of the 'Show code' views:

<TextBlock Visibility="Collapsed" Margin="5" Text="&lt;controls:AutoCompleteTagBox&#10;
           Name=&quot;AutoCompleteTagBoxWithStrings&quot;&#10;
           Margin=&quot;5&quot;&#10;
           ItemsSource=&quot;{Binding Names}&quot;&#10;
           FilterMode=&quot;Contains&quot; /&gt;&#10;
           &lt;ListBox&#10;
           ItemsSource=&quot;{Binding ElementName=AutoCompleteTagBoxWithStrings, Path=SelectedItems}&quot;&#10;
           Grid.Column=&quot;1&quot;&#10;
           BorderBrush=&quot;{StaticResource Blue}&quot; BorderThickness=&quot;1&quot; /&gt;"/>

As you can see, it doesn't look nice and once you update one of the controls you now have three places you need to change the XAML.

The next step is just to bind the TextBlock visibility and toggle it from 'Collapsed' to 'Visible'. But I want to know if there is a way to show the XAML in a textblock without having to hand write the string.

Thanks in advance for your advice!

1
Have you tried using XamlWriter.Save there is an example here.XAMlMAX
I tried, but since XamlWriter cannot serialize generic types and most of the workarounds try to make me re-write all our controls classes. That's not something we want to do just to show the XAML.Thomas Bouman
OK. I just looked at this post and to be fair it doesn't seem to be a lot of work if you just use the decorator for your Binding, unless of course it's not as simple as that?XAMlMAX
Yup, that was it! Thanks for the help!Thomas Bouman

1 Answers

2
votes

Following from XAMIMAX's comment you could use an easy converter to save the xaml to a string using XamlWriter and strip the xmlns namespaces for brevity.

public class XamlConverter : IValueConverter
{
    public readonly Regex xmlnsRegex = new Regex("xmlns=\".+\"");

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var source = value as FrameworkElement;
        if (source != null)
        {
            //Save xaml and strip xmlns namespaces
            var xaml = xmlnsRegex.Replace(System.Windows.Markup.XamlWriter.Save(source), "");

            return xaml;
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Example usage

<StackPanel>
    <StackPanel.Resources>
        <converters:XamlConverter x:Key="Converter_Xaml"/>
    </StackPanel.Resources>
    <Button x:Name="SourceButton" Content="Click Me" Margin="10"/>
    <TextBlock Text="{Binding ElementName=SourceButton, Converter={StaticResource Converter_Xaml}}" TextWrapping="Wrap"/>
</StackPanel>