wpfxamlwpf-stylexamlwriter

XamlWriter skips "x:Name" attribute while saving ResourceDictionary


Here's custom style:

<Style TargetType="{x:Type Button}">
    <Setter Property="Focusable" Value="false" />
    <Setter Property="Background" Value="{StaticResource AppBackBrush}"/>
    <Setter Property="Foreground" Value="{StaticResource AppBrush}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border BorderBrush="{StaticResource AppBrush}"
                        Name="content"
                        BorderThickness="1"
                        CornerRadius="3"
                        Background="{StaticResource AppBackBrush}"
                        >
                    <Grid Background="Transparent">
                        <Label Content="{TemplateBinding Content}"
                               HorizontalContentAlignment="Center"
                               VerticalContentAlignment="Center"
                               Grid.Row="0" Grid.Column="0"
                               Background="Transparent"
                               Style="{x:Null}"
                               Foreground="{TemplateBinding Foreground}"
                               Padding="{TemplateBinding Padding}"/>
                    </Grid>
                    <Border.RenderTransform>
                        <!-- push the content a bit to the left and the top -->
                        <TranslateTransform x:Name="translation"
                                            X="-1" Y="-1"/>
                    </Border.RenderTransform>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0"
                                                     To="0"
                                                     Storyboard.TargetName="translation"
                                                     Storyboard.TargetProperty="(TranslateTransform.X)"/>
                                    <DoubleAnimation Duration="0:0:0"
                                                     To="0"
                                                     Storyboard.TargetName="translation"
                                                     Storyboard.TargetProperty="(TranslateTransform.Y)"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0"
                                                     To="-1"
                                                     Storyboard.TargetName="translation"
                                                     Storyboard.TargetProperty="(TranslateTransform.X)"/>
                                    <DoubleAnimation Duration="0:0:0"
                                                     To="-1"
                                                     Storyboard.TargetName="translation"
                                                     Storyboard.TargetProperty="(TranslateTransform.Y)"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="content" Property="Opacity" Value="0.5" />
                    </Trigger>

                </ControlTemplate.Triggers>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I save this ResourceDictionary that contains this style to string like this:

XamlWriter.Save(s);

where s is ResourceDictionary. The problem is that when I get expected string, it looks so:

<Style TargetType=\"Button\" x:Key=\"{x:Type Button}\">
    <Style.Resources>
        <ResourceDictionary />
    </Style.Resources>
    <Setter Property=\"UIElement.Focusable\">
        <Setter.Value>
            <s:Boolean>False</s:Boolean>
        </Setter.Value>
    </Setter>
    <Setter Property=\"Panel.Background\">
        <Setter.Value>
            <SolidColorBrush>#FFF1F2F4</SolidColorBrush>
        </Setter.Value>
    </Setter>
    <Setter Property=\"TextElement.Foreground\">
        <Setter.Value>
            <SolidColorBrush>#FF13776A</SolidColorBrush>
        </Setter.Value>
    </Setter>
    <Setter Property=\"Control.Template\">
        <Setter.Value>
            <ControlTemplate TargetType=\"Button\">
                <Border BorderThickness=\"1,1,1,1\" CornerRadius=\"3,3,3,3\" BorderBrush=\"#FF13776A\" Background=\"#FFF1F2F4\" Name=\"content\">
                    <Border.RenderTransform>
                        <TranslateTransform X=\"-1\" Y=\"-1\" />
                    </Border.RenderTransform>
                    <Grid>
                        <Grid.Style>
                            <Style TargetType=\"Grid\">
                                <Style.Resources>
                                    <ResourceDictionary />
                                </Style.Resources>
                                <Setter Property=\"Panel.Background\">
                                    <Setter.Value>
                                        <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Grid.Style>
                        <Label Content=\"{TemplateBinding ContentControl.Content}\" Background=\"#00FFFFFF\" Foreground=\"{TemplateBinding TextElement.Foreground}\" HorizontalContentAlignment=\"Center\" VerticalContentAlignment=\"Center\" Padding=\"{TemplateBinding Control.Padding}\" Style=\"{x:Null}\" Grid.Column=\"0\" Grid.Row=\"0\" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property=\"ButtonBase.IsPressed\">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <Storyboard.Children>
                                        <DoubleAnimation To=\"0\" Duration=\"00:00:00\" Storyboard.TargetName=\"translation\" Storyboard.TargetProperty=\"(TranslateTransform.X)\" />
                                        <DoubleAnimation To=\"0\" Duration=\"00:00:00\" Storyboard.TargetName=\"translation\" Storyboard.TargetProperty=\"(TranslateTransform.Y)\" />
                                    </Storyboard.Children>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                    <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <Storyboard.Children>
                                <DoubleAnimation To=\"-1\" Duration=\"00:00:00\" Storyboard.TargetName=\"translation\" Storyboard.TargetProperty=\"(TranslateTransform.X)\" />
                                <DoubleAnimation To=\"-1\" Duration=\"00:00:00\" Storyboard.TargetName=\"translation\" Storyboard.TargetProperty=\"(TranslateTransform.Y)\" />
                            </Storyboard.Children>
                        </Storyboard>
                    </BeginStoryboard>
                    </Trigger.ExitActions>
                        <Trigger.Value>
                            <s:Boolean>True</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <Trigger Property=\"UIElement.IsEnabled\">
                        <Setter Property=\"UIElement.Opacity\" TargetName=\"content\">
                            <Setter.Value>
                                <s:Double>0.5</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>False</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Please take a look at TranslateTransform in Border.RenderTransform. In the ResourceDictionary it has x:Name="translation", but the name is missing in the output string.

Where was I mistaken or is this a bug? Thanks in advance.


Solution

  • According to this MSDN blog post, "some markup extensions, such as {x:Static}, are resolved at load-time by XamlReader and the markup extension itself is discarded, so there is no means for XamlWriter to re-produce it." It looks like x:Name is one of those markup extensions that is lost.

    It looks like you are trying to create two styles - an original and an extended one - that both implicitly target button (presumably in different scopes). If that is the case, you can create a base style in a resource both styles above can reference, then use Style's BasedOn property to keep from duplicating the template.