Search code examples
wpfbuttonuser-controls

WPF style overwritten when content applied to UserControl


I have a UserContol for a hyperlink. I need to dynamically set the content of the button to a database value.

I have looked at this link [1]:Custom button user control style overwritten when content is set and it seems I have most everything from that post. But I get errors when I try to set the content in the user control. I am not a WPF programmer so any help in small words would be appreciated.

USER CONTROL

`

<UserControl x:Class="DDC.Controls.LinkButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             x:Name="UserControl">

    <UserControl.Resources>
        <Style x:Key="LinkButtonStyle"    TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/>
            <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
            <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Padding" Value="5,0,0,0" />
            <Setter Property="ToolTip" Value="Click to Follow Link" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                                                <ContentPresenter 

                                  VerticalAlignment="Top">
                            <ContentPresenter.Resources>
                                <Style TargetType="{x:Type TextBlock}">
                                    <Setter Property="TextDecorations" Value="Underline" />
                                    <Setter Property="TextWrapping" Value="Wrap"/>
                                </Style>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Foreground" Value="LightGray" />
                </Trigger>
            </Style.Triggers>
        </Style>

    </UserControl.Resources>

    <Grid>
        <Button Name ="btnLinkAddress" 
                Style="{DynamicResource LinkButtonStyle}" 
                Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type LinkButton}}}"
                Width="Auto" 
                Height="Auto"  
                UseLayoutRounding="True" 
                Click="LinkButton_Click" >
        </Button>
    </Grid>
</UserControl>

C# Class

public partial class LinkButton : UserControl
    {

        public new static   DependencyProperty ContentProperty =
           DependencyProperty.Register("Content", typeof(object), typeof(LinkButton));

        public new object Content
        {
            get { return (string)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        private void LinkButton_Click(object sender, RoutedEventArgs e)
        {
            Button btn = (Button)sender;
            TextBlock tb = (TextBlock)btn.Content;
            Uri uri = new System.Uri(tb.Text);
           // Uri uri = new System.Uri(btn.Content.ToString());

            Process.Start(new ProcessStartInfo(uri.AbsoluteUri));
            e.Handled = true;
        }
        public LinkButton()
        {
            InitializeComponent();
        }

ERRORS

I get these errors when trying to set the content in the user control

Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type LinkButton}}}"`

LinkButton is not supported in a Windows Presentation Foundation (WPF) project.

Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"

Logical tree depth exceeded while traversing the tree. This could indicate a cycle in the tree.


Solution

  • Rename the property to something else than Content:

    public partial class LinkButton : UserControl
    {
        public static DependencyProperty ButtonContentProperty =
           DependencyProperty.Register("ButtonContent", typeof(object), typeof(LinkButton));
    
        public object ButtonContent
        {
            get { return (string)GetValue(ButtonContentProperty); }
            set { SetValue(ButtonContentProperty, value); }
        }
    
        private void LinkButton_Click(object sender, RoutedEventArgs e)
        {
            ...
        }
        public LinkButton()
        {
            InitializeComponent();
        }
    }
    

    ...and bind to it like this:

    <Button Name ="btnLinkAddress" 
            Style="{DynamicResource LinkButtonStyle}" 
            Content="{Binding Path=ButtonContent, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
            Width="Auto" 
            Height="Auto"  
            UseLayoutRounding="True" 
            Click="LinkButton_Click" >
    

    If you want to set the AncestorType to LinkButton, you should define a namespace mapping:

    <Button xmlns:local="clr-namespace:DDC.Controls"
            Name ="btnLinkAddress" 
            Style="{DynamicResource LinkButtonStyle}" 
            Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type local:LinkButton}}}"
            Width="Auto" 
            Height="Auto"  
            UseLayoutRounding="True" 
            Click="LinkButton_Click" >