Sceen Sceen - 18 days ago 10
C# Question

WPF Databinding in ControlTemplate not working C#

I try to bind a simple bool to a checkbox and a datatrigger in a controltemplate, but nothing is working. The checkbox is only for test purpose. I already went through the posts here, but most problems are caused by setting a property directly and not in the style, thus overwriting it. The datatrigger using the mouseover property is working just fine. Its only the binding to the bool which doesn't work.

My Code so far:
cs:

public partial class HostFrame : UserControl
{
public bool test { get; set; }

public HostFrame()
{
test = true;
InitializeComponent();
}
}


Xaml:

<UserControl x:Class="OwnDrawingv2.Elements.HostFrame"
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"
xmlns:local="clr-namespace:OwnDrawingv2.Elements"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="{x:Type local:HostFrame}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:HostFrame}">
<Grid Background="LightBlue" Name="host_grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<ContentPresenter Name="content" Grid.Row="1" Grid.Column="1" />
<CheckBox Grid.Column="0" Grid.Row="0" IsChecked="{Binding Path=test}"> <!--Test prupose-->
</CheckBox>
<Image Grid.Column="1" Grid.Row="0" Name="attention" Width="30" Height="30" Source="/attention_icon.png">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=test}" Value="true">

<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Ellipse Grid.Column="0" Grid.Row="1" Width="10" Height="10" Fill="Black">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Hidden"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=content, Path=IsMouseOver}" Value="true">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse Grid.Column="2" Grid.Row="1" Width="10" Height="10" Fill="Black">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Hidden"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=content, Path=IsMouseOver}" Value="true">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
</UserControl>


UPDATE: I got an answer for my original question and I understand this. But why are there tutorials in the web, which seem to work without the relativesource?
UPDATE2: I missed one answers information about Datacontext, thank you. The problem is solved.

Answer

if you do the following IsChecked="{Binding Path=test}" that means your UserControl class is the DataContext of it self (or you didn't say that). So you have 2 solutions (I guess)

1- Move your Test property to your ViewModel and do your Binding. 2- Use RelativeResource and FindAncestor method ({Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}})

PS: IF your HostFrame inherits from Control,UIELement..., It would be better to define a DependencyProperty and do a TemplateBinding

Comments