How to use Attached property within a style?
Here is how you can set your attached property in a style
<Style x:Key="ToolBarButtonStyle" TargetType="Button">
<Setter Property="PrismExt:ImgSourceAttachable.ImgSource"
Value="./Images/New.png"/>
<!--...-->
</Style>
When binding to attached properties then the Path should be within parentheses so try to use RelativeSource
Binding with TemplatedParent
instead
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image x:Name="toolbarImage"
Source="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(PrismExt:ImgSourceAttachable.ImgSource)}"
Width="48"
Height="48">
</Image>
</ControlTemplate>
</Setter.Value>
</Setter>
Edit: The above code works in WPF, in Silverlight the Image
shows in runtime but it fails in the designer with an exception. You can use the following code in the PropertyChangedCallback to get the Image
as a workaround
private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Button button = d as Button;
Image image = GetVisualChild<Image>(button);
if (image == null)
{
RoutedEventHandler loadedEventHandler = null;
loadedEventHandler = (object sender, RoutedEventArgs ea) =>
{
button.Loaded -= loadedEventHandler;
button.ApplyTemplate();
image = GetVisualChild<Image>(button);
// Here you can use the image
};
button.Loaded += loadedEventHandler;
}
else
{
// Here you can use the image
}
}
private static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
DependencyObject v = (DependencyObject)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
Houman
I'm a thinker and a dreamer. Love pets but don't have any. I'm a passionate tech entrepreneur.
Updated on November 30, 2020Comments
-
Houman over 3 years
I have created an Image within a ButtonStyle. Now I have created an Attached Property so that I can set the Source for that Image. Should be straight forward but I am stuck with it.
This is my shortened ButtonStyle:
<Style x:Key="ToolBarButtonStyle" TargetType="Button"> ... <Image x:Name="toolbarImage" Source="{TemplateBinding PrismExt:ImageSourceAttachable:ImageSource}" Width="48" Height="48" /> ... </Style>
And this is the attached property definition, Note that I have no idea how to fix the callback, as the dependencyproperty seems to be the button instead of the image. And Button doesn't expose my Image within its style. Its tricky.
namespace SalesContactManagement.Infrastructure.PrismExt { public class ImgSourceAttachable { public static void SetImgSource(DependencyObject obj, string imgSource) { obj.SetValue(ImgSourceProperty, imgSource); } public static string GetImgSource(DependencyObject obj) { return obj.GetValue(ImgSourceProperty).ToString(); } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty ImgSourceProperty = DependencyProperty.RegisterAttached("ImgSource", typeof(string), typeof(ImgSourceAttachable), new PropertyMetadata(Callback)); private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e) { //((Button)d).Source = new BitmapImage(new Uri(Application.Current.Host.Source, e.NewValue.ToString())); } } }
This is how I set the image source within XAML:
<Button PrismExt:ImgSourceAttachable.ImgSource="./Images/New.png" Style="{StaticResource ToolBarButtonStyle}" />
Any ideas please? Many Thanks,
-
Houman almost 13 yearsThank you. This code compiles now, however I still dont see the images. I am pretty sure its because the CallBack of Attached Property is empty. However the "DependencyObject d" there is the button itself. I dont understand...
-
Fredrik Hedblad almost 13 yearsI just noticed your question had both WPF and Silverlight tags, my answer was for WPF. I'll try it out for Silverlight.
-
Houman almost 13 yearsYou are right. apologies. I thought regarding attached properties they would be no different. :)
-
Fredrik Hedblad almost 13 yearsUpdated my answer. That code worked in runtime on my end, but failed in the designer. Added code to get the image in the callback
-
Houman almost 13 yearsThank you so much. It works like a charm. I don't think I could have done it without your help. :)
-
Fredrik Hedblad almost 13 yearsSure thing, glad I could help!