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,
An 'attached' property is a concept defined by Extensible Application Markup Language (XAML). It is intended to be used as a type of global property that can be set on any object.
Attached properties allows container to create a property which can be used by any child UI elements whereas dependency property is associated with that particular elements and can help in notification of changes and reacting to that changes. Attached properties are basically meant for the container elements.
Attached properties are properties which can be set on any wpf object (basically, at least a DependencyObject) via the DependencyObject. SetValue method. The purpose for this mechanism is to "attach" to other objects information needed by parent objects, not the child objects themselves. For example, the Grid.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With