{Binding} not working in ContentTemplate in Custom Control

guess_me_if_u_can 126 Reputation points
2022-06-07T12:24:11.973+00:00

I have tried to override the default Button as ButtonWithLoader. Everything is working fine except a specific case that {Binding} is not working in ContentTemplate.

209142-sgxkr.png

Please refer to the link below for the complete source code of the above custom control.

ButtonWithLoader.zip

Universal Windows Platform (UWP)
Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
787 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Roy Li - MSFT 33,366 Reputation points Microsoft Vendor
    2022-06-08T06:53:39.423+00:00

    Hello,

    Welcome to Microsoft Q&A!

    The issue is that when you are using binding in the TextBlock, the TextBlock can't find the datacontext for itself. So the binding is actually invalid. You need to explicitly set the binding path and the source for the TextBlock. So you need to give the local:ButtonWithLoader a name and set the path in your code.

    Like this:

       <!--Custom Button not working with Binding-->  
            <local:ButtonWithLoader x:Name="Myloader" Grid.Row="1" Background="Gray" Margin="0,20,0,0" Width="100" Content="Wrapping Text 123">  
                <local:ButtonWithLoader.ContentTemplate>  
                    <DataTemplate>  
                        <TextBlock Text="{Binding Path=Content,ElementName=Myloader}" TextWrapping="Wrap"/>  
                    </DataTemplate>  
                </local:ButtonWithLoader.ContentTemplate>  
            </local:ButtonWithLoader>  
    

    I've noticed that you've asked the same question on StackOverflow. I'll give an answer there as well.

    Update:

    I checked your custom style and dig it a little bit, I found that you've already defined the Content property in the style instead of the ContentTemplate property. You added a ProgressRing control in it. I think you want to create a button that could show text and the ProgressRing at the same time, right?

    But the code you are using now is trying to assign another DataTemplate to the ContentTemplate property. This will override the content of the Button. The custom grid that you put in the custom style will be covered by the DataTemplate. No matter whether the binding work or not, the ProgressRing won't show. I guess this is not the behavior that you want to get.

    If you just want to set string data for the custom Button, Then you should just use the content property instead of adding another DataTemplate which contains just a TextBlock with binding.

      <local:ButtonWithLoader x:Name="Myloader2" Grid.Row="1" IsLoading="True" Background="Gray" Margin="0,20,0,0" Width="100" Content="{Binding text}">  
                  
            </local:ButtonWithLoader>  
    

    If you have other requirements for the custom button, you should move the custom part of the ContentPresenter.Content of the style, and put them into the ContentTemplate. Like:

     <Grid.Resources>  
                <DataTemplate x:Key="ButtonTemplate" >  
                    <Grid Margin="0,0,-28,0" Padding="{Binding ContentPadding}">  
                        <Grid.ColumnDefinitions>  
                            <ColumnDefinition Width="Auto" />  
                            <ColumnDefinition Width="Auto" />  
                        </Grid.ColumnDefinitions>  
                        <ContentPresenter x:Name="ButtonContent" Content="{Binding Content,RelativeSource= {RelativeSource Mode=TemplatedParent}}">  
                            <ContentPresenter.RenderTransform>  
                                <CompositeTransform />  
                            </ContentPresenter.RenderTransform>  
                        </ContentPresenter>  
                        <ProgressRing Margin="10,0,0,0" x:Name="ButtonLoading"   
                                      Grid.Column="1"   
                                      IsActive="{Binding IsLoading}"  
                                      Foreground="{Binding Foreground}"  
                                      MinWidth="12" MinHeight="12" Height="18" Width="18">  
                            <ProgressRing.RenderTransform>  
                                <CompositeTransform />  
                            </ProgressRing.RenderTransform>  
                        </ProgressRing>  
                    </Grid>  
                </DataTemplate>  
            </Grid.Resources>  
    
       <local:ButtonWithLoader x:Name="Myloader"  
                                    Grid.Row="0"  
                                    Background="Gray"  
                                    Margin="0,20,0,0"  
                                    Width="200"   
                                    Content="Wrapping Text 123"  
                                    ContentTemplate="{StaticResource ButtonTemplate}"/>  
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.