I am relatively new to WPF and am trying to understand Attached Properties to use them in my test application I am using as a learning base. The AP is in it'own source file named AP.cs that lives in namespace WPFPages.ViewModels.
So I have created a simple AP as shown below that stores an int value.
public class AP: DependencyObject
{
public static int Gettest ( DependencyObject obj )
{
return ( int ) obj . GetValue ( testProperty );
}
public static void Settest ( DependencyObject obj, int value )
{
obj . SetValue ( testProperty, value );
}
public static readonly DependencyProperty testProperty =
DependencyProperty . RegisterAttached ( "test", typeof ( int ), typeof ( AP ), new PropertyMetadata ( 2 ), Ontestchanged);
private static bool Ontestchanged ( object value )
{
Console . WriteLine ($"test value changed to {value}");
return true;
}
}
In my XAML I have set the value using models:AP.test="21" which works as expected, verfied by my WriteLine debug in the AP.
However, I want to have this value as a column in a ListBox, and therefore have a DataTemplate that has the following entry:
<TextBlock x:Name="tst"
Text="{Binding Path=(models:AP.test), RelativeSource={RelativeSource Self}}"
Width="55"/>
Sadly, I only see the default set in the AP in my ListBox, NOT the value of 21. I have set it to in my ListBox properties. I have declared the namespace in my XAML files as shown below.
xmlns:models="clr-namespace:WPFPages.ViewModels"
I have read every possible article on attached properties, and have tried more variations on a theme in terms of syntax to make this work, but with no success at all. So far I have spent 3 days trying to get this simple AP to work.
I feel sure it is something simple due to my inexperience with the complexities of Binding, but would greatly appreciate some assistance in getting to the bottom of how I make this work, as I can see how powerful the AP's can be, if only I can make them work of course?.
UPDATE instead of using Comment :
<ListBox x:Name="listboxclass"
ItemContainerStyle="{StaticResource lvItemStyle1}"
BorderThickness="2"
BorderBrush="{StaticResource Blue0}"
FontWeight="Normal"
FontSize="14" Margin="0,0,0,164" >
<ListBoxItem
Height="45"
models:AP.test="21"/>
The relevant Style code is:
Hope this clarifies it. I am happy to get the same value appearing in the column selected for now.
<Style x:Key="lvItemStyle1" TargetType="{x:Type ListBoxItem}">
<!--<Setter Property="Background" Value="{Binding (models:AP.Background)}"/>-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<!--<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<Border.Background>
<SolidColorBrush x:Name="borderbckgrnd" Color="{TemplateBinding models:AP.Background}" />
</Border.Background>
<ContentPresenter x:Name="contentpresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
</ContentPresenter>
</Border>-->
<!--I have tried ALL of these & they ALL cause Exceptions on loading
"{Binding models:AP.test}"
"{Binding Path=(models:AP.test)}"
"{Binding (models:AP.test)}"
"{Binding Source=models:AP.test}"
"{TemplateBinding models:AP.test}"-->
<Border x:Name="Bd" >
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding CustomerId}"
Height="{Binding ActualHeight, ElementName=NwCustomerDataTemplateBorder1}"
Width="50"
Padding="1"
x:Name="CustomerId"/>
<!--NB Output window shows :
AP : test value changed to 2
AP : test value changed to 21
so it is definitely being set.
but the field is empty in the list when run-->
<TextBlock x:Name="tst"
Text="{Binding Path=models:Attach.test}"
Foreground="Red"
Width="55"/>
<!--this does not give error, but does not work either
Height="{Binding Path=models:AP.test, RelativeSource={RelativeSource Self}}"-->
<TextBlock Text="{Binding CompanyName}" Width="165" Padding="1" x:Name="CompanyName"/>
<TextBlock Text="{Binding ContactName}" Width="135" Padding="1" x:Name="ContactName"/>
<TextBlock Text="{Binding ContactTitle}" Width="40" Padding="1" x:Name="ContactTitle"/>
<TextBlock Text="{Binding Address}" Width="150" Padding="1" x:Name="Address"/>
<TextBlock Text="{Binding City }" Width="80" Padding="1" x:Name="City"/>
<TextBlock Text="{Binding PostalCode}" Width="75" Padding="1" x:Name="PostalCode"/>
<TextBlock Text="{Binding Country}" Width="75" Padding="1" x:Name="Country"/>
<TextBlock Text="{Binding Phone}" Width="95" Padding="1" x:Name="Phone"/>
<TextBlock Text="{Binding Fax}" Width="95" Padding="1" x:Name="Fax"/>
</StackPanel>
</Border>
<!-- ... -->
This is how you could bind to the attached property of the parent
ListBoxin theItemTemplate: