Image.Height TemplateBinding does not work - wpf

I have created a CustomControl implemented from Button class in WPF.
public class ImageButton : Button
{
...
public int ImageHeight
{
get { return (int)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public static readonly DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(int), typeof(ImageButton), new UIPropertyMetadata(32));
...
}
And I have resource template like this:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type custom:ImageButton}">
<Border>
<StackPanel>
<Image Name="image" Height="{TemplateBinding ImageHeight}"/>
<TextBlock Text="{TemplateBinding Text}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
ImageHeight dependecy property doesn't binding.
When I write like as below it works successful.
Height="32"
What is wrong with this?

Did you try using {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Progress} instead ?
See these answers for more details...
WPF TemplateBinding vs RelativeSource TemplatedParent
Binding custom dependency property to custom WPF style
hope this helps

Related

ControlTemplate LayoutTransform Binding System.Windows.Data Error 2 or 4

I'm creating a custom UserControl which will act as a container, showing a self-sized watermark behind its Content.
The relevant part of the ControlTemplate (I'll give you the full thing below) is
<TextBlock
Text="{TemplateBinding WatermarkText}"
Foreground="{TemplateBinding WatermarkBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold">
<TextBlock.LayoutTransform>
<RotateTransform Angle="{Binding WatermarkAngle,RelativeSource={RelativeSource AncestorType={x:Type local:WatermarkUserControl}}}"/>
</TextBlock.LayoutTransform>
</TextBlock>
My UserControl has dependency properties for WatermarkText, WatermarkBrush, WatermarkAngle and WatermarkVisibility (I'll include that below). Notice that the TemplateBindings for WatermarkText, WatermarkBrush and WatermarkVisibility all work fine.
Using TemplateBinding for WatermarkAngle didn't work, because TemplateBinding is a lightweight "binding", so it doesn't support inheritance context. The WatermarkAngle binding that I ended up with (above) actually works; and yet a binding error is reported:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'RelativeSource FindAncestor,
AncestorType='[redacted namespace].WatermarkUserControl', AncestorLevel='1''.
BindingExpression:Path=WatermarkAngle; DataItem=null; target element
is 'RotateTransform' (HashCode=59772470); target property is 'Angle'
(type 'Double')
So is there a way of doing this better, which avoids the error being reported? And why is it reporting an error with the binding, given that the binding is actually working? (If I change the value, it reflects that.)
That concludes the question. Here are all the parts you need, to satisfy MCVE:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class WatermarkUserControl : UserControl
{
public static readonly DependencyProperty WatermarkTextProperty =
DependencyProperty.Register(nameof(WatermarkText), typeof(string), typeof(WatermarkUserControl), new PropertyMetadata("Watermark"));
public static readonly DependencyProperty WatermarkBrushProperty =
DependencyProperty.Register(nameof(WatermarkBrush), typeof(Brush), typeof(WatermarkUserControl), new PropertyMetadata(new SolidColorBrush(Colors.LightGray)));
public static readonly DependencyProperty WatermarkAngleProperty =
DependencyProperty.Register(nameof(WatermarkAngle), typeof(double), typeof(WatermarkUserControl), new PropertyMetadata(0d));
public static readonly DependencyProperty WatermarkVisibilityProperty =
DependencyProperty.Register(nameof(WatermarkVisibility), typeof(Visibility), typeof(WatermarkUserControl), new PropertyMetadata(Visibility.Visible));
public string WatermarkText
{
get { return (string)GetValue(WatermarkTextProperty); }
set { SetValue(WatermarkTextProperty, value); }
}
public Brush WatermarkBrush
{
get { return (Brush)GetValue(WatermarkBrushProperty); }
set { SetValue(WatermarkBrushProperty, value); }
}
public double WatermarkAngle
{
get { return (double)GetValue(WatermarkAngleProperty); }
set { SetValue(WatermarkAngleProperty, value); }
}
public Visibility WatermarkVisibility
{
get { return (Visibility)GetValue(WatermarkVisibilityProperty); }
set { SetValue(WatermarkVisibilityProperty, value); }
}
}
ResourceDictionary:
<Style x:Key="WatermarkUserControlBaseStyle" TargetType="local:WatermarkUserControl">
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:WatermarkUserControl">
<Grid>
<local:NoSizeDecorator Visibility="{TemplateBinding WatermarkVisibility}">
<Viewbox>
<TextBlock
Text="{TemplateBinding WatermarkText}"
Foreground="{TemplateBinding WatermarkBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold">
<TextBlock.LayoutTransform>
<RotateTransform Angle="{Binding WatermarkAngle,RelativeSource={RelativeSource AncestorType={x:Type local:WatermarkUserControl}}}"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Viewbox>
</local:NoSizeDecorator>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DraftWatermarkStyle" TargetType="local:WatermarkUserControl" BasedOn="{StaticResource WatermarkUserControlBaseStyle}">
<Setter Property="WatermarkText" Value="DRAFT"/>
<Setter Property="WatermarkBrush" Value="LightPink"/>
<Setter Property="WatermarkAngle" Value="-20"/>
</Style>
NoSizeDecorator is defined here.
Example of use:
<local:WatermarkUserControl
Style="{StaticResource DraftWatermarkStyle}"
WatermarkVisibility="True">
<StackPanel>
<Label Content="Mr Smith"/>
<Label Content="1 High Street"/>
<Label Content="London"/>
</StackPanel>
</local:WatermarkUserControl>
I've worked out a way of doing it. It has made the error go away, and it still seems to work, and I haven't spotted any side effects yet.
I declared the RotateTransform as a local resource inside the Viewbox in the ControlTemplate, and then bound that as a StaticResource to the LayoutTransform property of the TextBlock. So the new version of the Viewbox from the question looks like this:
<Viewbox>
<Viewbox.Resources>
<RotateTransform x:Key="RotateWatermarkTransform" Angle="{Binding WatermarkAngle,RelativeSource={RelativeSource TemplatedParent}}"/>
</Viewbox.Resources>
<TextBlock
Text="{TemplateBinding WatermarkText}"
Foreground="{TemplateBinding WatermarkBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
LayoutTransform="{StaticResource RotateWatermarkTransform}"/>
</Viewbox>

How to set a property of a custom control from the main window?

I have a custom control, this is the generic.axml code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Calendario"
xmlns:MyNamespace="clr-namespace:Calendario;assembly=Calendario"
xmlns:Converters="clr-namespace:Calendario.Converters">
<Converters:DateConverter x:Key="DateConverter"></Converters:DateConverter>
<Converters:DayBorderColorConverter x:Key="DayBorderColorConverter"></Converters:DayBorderColorConverter>
<Style TargetType="{x:Type local:CalendarioPersonalizado}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioPersonalizado}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<TextBlock Text="{Binding Date}" />
<Grid Height="30" DockPanel.Dock="Top">
</Grid>
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{Binding ColorRecuadroExterno, Mode=TwoWay}" BorderThickness="1" Padding="0">
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And I have my Calendario.cs with the dpendency property:
public static readonly DependencyProperty ColorRecuadroExternoProperty = DependencyProperty.Register("ColorRecuadroExterno", typeof(Brush), typeof(CalendarioPersonalizado));
public Brush ColorRecuadroExterno
{
get { return (Brush)GetValue(ColorRecuadroExternoProperty); }
set { SetValue(ColorRecuadroExternoProperty, value); }
}
And later in my main windows I use the control:
<local:CalendarioPersonalizado x:Name="cCalendario" ColorRecuadroExterno="Green"/>
The problem is that the border of the day in the calendar is not set to green like I have tried to set in the main window.
Also in the code behid I have tried this:
cCalendario.ColorRecuadroExterno = System.Windows.Media.Brushes.Green;
But the the color is not set.
What I want to do is set the color of the border in my custom cotrol from my main application.
Thanks.
If you put a Callback method in your local:CalendarioPersonalizado class and set your backround in this callback method. I think it is going to work.
public static readonly DependencyProperty ColorRecuadroExternoProperty = DependencyProperty.Register("ColorRecuadroExterno", typeof(Brush), typeof(CalendarioPersonalizado),
new PropertyMetadata(Brushes.Brown, Callback));
private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CalendarioPersonalizado obj = d as CalendarioPersonalizado;
obj.ColorRecuadroExterno.Background = (Brush)e.NewValue;
}
Your DependencyProperty is of type Brush. You can't implicitly convert "Green" to a Brush.
You either need to use a converter to convert a string representation of a color to a brush, or make your property type Color, and bind it to an appropriate property.

UserControl multiple datatemplate + templateselector

I need to show data inside a usercontrol in different ways depending on a flag.
To achieve this i tried the following, but using this control in the main view shows nothing.
<UserControl DataContext="**self**">
<UserControl.Resources>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</DataTemplate>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</StackPanel>
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}" />
</UserControl>
What am i doing wrong?
Is there a better way to achieve that?
Thank to EdPlunkett and more research i found out it is better to
use a ContentPresenter here and instead of binding on DataContext=this bind like this (as alsways suggested when writing a UserControl)
DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}"
Code:
<UserControl.Resources>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" Width="64" Height="64" />
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}">
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}">
</Grid>
Your ContentPresenter idea is the correct way to do it with a DataTemplateSelector, and I should have thought of it myself.
But here's yet another way to do it, which unlike my first answer, actually solves all the problems you're having:
XAML (in practice the Style would probably be defined in a separate ResourceDictionary):
<Window
x:Class="TestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestApplication"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="MainWindow" Height="350" Width="525"
>
<Window.Resources>
<Style TargetType="local:TestControl">
<Setter Property="Background" Value="Gainsboro" />
<Style.Triggers>
<!-- The 0 value for the InputMode enum is Mouse, so this will be the default. -->
<Trigger Property="InputMode" Value="Mouse">
<Setter Property="Background" Value="Wheat" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="InputMode" Value="Touch">
<Setter Property="Background" Value="LightSkyBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image
Source="{TemplateBinding ImageUri}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
/>
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<local:TestControl
ImageHeight="100"
ImageWidth="100"
Text="This is the test control"
ImageUri="http://www.optimizeagency.com/wp-content/uploads/2015/09/GoogleLogo.jpg"
/>
</Grid>
</Window>
C#:
using System;
using System.Windows;
using System.Windows.Controls;
namespace TestApplication
{
class TestControl : Control
{
public TestControl()
{
// If input mode may change at runtime, you'll need an event that fires when that
// happens and updates this property.
// UIUtilities.GetInputMode() is just a stub in this example.
InputMode = UIUtilities.GetInputMode();
}
#region InputMode Property
public InputMode InputMode
{
get { return (InputMode)GetValue(InputModeProperty); }
set { SetValue(InputModeProperty, value); }
}
public static readonly DependencyProperty InputModeProperty =
DependencyProperty.Register("InputMode", typeof(InputMode), typeof(TestControl),
new PropertyMetadata(InputMode.Mouse));
#endregion InputMode Property
#region Text Property
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(TestControl),
new PropertyMetadata(null));
#endregion Text Property
#region ImageUri Property
// The TemplateBinding in the template can't coerce a string to an
// ImageSource, so we have to make that happen elsewhere.
public ImageSource ImageUri
{
get { return (ImageSource)GetValue(ImageUriProperty); }
set { SetValue(ImageUriProperty, value); }
}
public static readonly DependencyProperty ImageUriProperty =
DependencyProperty.Register("ImageUri", typeof(ImageSource), typeof(TestControl),
new PropertyMetadata(null));
#endregion ImageUri Property
#region ImageHeight Property
public float ImageHeight
{
get { return (float)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public static readonly DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageHeight Property
#region ImageWidth Property
public float ImageWidth
{
get { return (float)GetValue(ImageWidthProperty); }
set { SetValue(ImageWidthProperty, value); }
}
public static readonly DependencyProperty ImageWidthProperty =
DependencyProperty.Register("ImageWidth", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageWidth Property
}
#region This stuff belongs in a different file
public static class UIUtilities
{
public static InputMode GetInputMode()
{
// Here you'd do whatever you're already doing to detect the input mode
return InputMode.Touch;
}
}
public enum InputMode
{
Mouse,
Touch
}
#endregion This stuff belongs in a different file
}

How to convert a manually created WPF Menuitem into a Template / Style Resource / Control Template

I have manualy created a MenuItem. Now I want it as a Template / Style Resource / Control Template - whatever the best is for this Task.
My MenuItem looks like this (I know short Code):
<MenuItem
x:Name="Quit" << OUTSIDE TEMPLATE
Command="{Binding ShutdownCommand}"> << OUTSIDE TEMPLATE
<MenuItem.Header>
<StackPanel
Orientation="Horizontal">
<TextBlock
Width="150"
Text="Quit ERD Builder"/> << OUTSIDE TEMPLATE
<TextBlock
Width="80"
Margin="0,2,0,0"
TextAlignment="Right">
<Border
Padding="4,0,4,0"
BorderBrush="#B0B0B0"
Background="#fff"
BorderThickness="1"
CornerRadius="6">
<TextBlock
Width="Auto"
Text="Alt+F4" << OUTSIDE TEMPLATE
FontSize="10"
Foreground="#555" />
</Border>
</TextBlock>
</StackPanel>
</MenuItem.Header>
<MenuItem.Icon>
<Image
Width="16"
Height="16"
Margin="0,0,5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderOptions.BitmapScalingMode="HighQuality"
SnapsToDevicePixels="True">
<Image.Source>
<BitmapImage
UriSource="/ERDBuilder;component/icons/bw/102-walk.png" /> << OUTSIDE TEMPLATE
</Image.Source>
</Image>
</MenuItem.Icon>
The Lines I declared with << OUTSIDE TEMPLATE are the Lines I want declare in the MenuItem and not in the Template.
I had have already tried some Styles but "Background" for e.g. wont work for some Reason. I am able to change the "FontSize" but not the "Background" Color:
<Style
x:Key="TopTaskBarMenuitem"
TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#ffff00" /> << DONT WORK
<Setter Property="FontSize" Value="20" /> << WORKS
</Trigger>
</Style.Triggers>
<Setter Property="Foreground" Value="#000" /> << WORKS
<Setter Property="BorderThickness" Value="1" /> << WORKS
<Setter Property="Width" Value="150"/> << WORKS
This is the Menu how it looks if I `XAML' it manually:
Manualy created Menuitem (I am not allowed to upload Images here ?!)
And this is the Menuitem with the static Style Resource:
Menuitem with Style Resource
As you can see, the "Background" Color wont affect the Menuitem.
If I could wish me something I would have in the End something like this on the "Menuitem"-Side:
<MenuItem
Style="{StaticResource TopTaskBarMenuitem}" << TEMPLATE / STYLE BINDING
x:Name="Quit" << OUTSIDE TEMPLATE
Command="{Binding ShutdownCommand}" << OUTSIDE TEMPLATE
MyHeaderText="Quit ERD Builder"/> << OUTSIDE TEMPLATE
MyShortcutText="Alt+F4" << OUTSIDE TEMPLATE
MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png" /> << OUTSIDE TEMPLATE
Thanks a lot to all they will Help!
PS: The last Codeline are missing on all three Code-Postings here. I dont know why. I am not able to fix this.
Dirk
To acquire this you have to create your own control deriving from MenuItem.
All you need to do is create the control class using DependencyProperties to make use of all its benefits, read this for more:
namespace MyControls
{
class MyMenuItem : MenuItem
{
public string MyHeaderText
{
get { return (string)GetValue(MyHeaderTextProperty); }
set { SetValue(MyHeaderTextProperty, value); }
}
public static readonly DependencyProperty MyHeaderTextProperty = DependencyProperty.Register("MyHeaderText", typeof(string), typeof(MyMenuItem));
public string MyShortcutText
{
get { return (string)GetValue(MyShortcutTextProperty); }
set { SetValue(MyShortcutTextProperty, value); }
}
public static readonly DependencyProperty MyShortcutTextProperty = DependencyProperty.Register("MyShortcutText", typeof(string), typeof(MyMenuItem));
public string MyUriSource
{
get { return (string)GetValue(MyUriSourceProperty); }
set { SetValue(MyUriSourceProperty, value); }
}
public static readonly DependencyProperty MyUriSourceProperty = DependencyProperty.Register("MyUriSource", typeof(string), typeof(MyMenuItem));
}
}
Now you are able to instantiate your control, but you still need to "retemplate" it:
<mc:MyMenuItem MyHeaderText="Quit ERD Builder" MyShortcutText="Alt+F4" MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png">
<mc:MyMenuItem.Style>
<Style TargetType="mc:MyMenuItem">
<Style.Setters>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="150" Text="{Binding Mode=TwoWay, Path=MyHeaderText, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}"/>
<TextBlock Width="80" Margin="0,2,0,0" TextAlignment="Right">
<Border Padding="4,0,4,0" BorderBrush="#B0B0B0" Background="#fff" BorderThickness="1" CornerRadius="6">
<TextBlock Width="Auto" Text="{Binding Mode=TwoWay, Path=MyShortcutText, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}" FontSize="10" Foreground="#555" />
</Border>
</TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Icon">
<Setter.Value>
<Image Width="16" Height="16" Margin="0,0,5,0" HorizontalAlignment="Center" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" Source="{Binding Mode=OneWay, Path=MyUriSource, RelativeSource={RelativeSource FindAncestor, AncestorType=mc:MyMenuItem}}" />
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</mc:MyMenuItem.Style>
</mc:MyMenuItem>
Don't forget to reference the namespace of this new control in your window (or wherever you may put this control) tag:
xmlns:mc="clr-namespace:MyControls"
It's possible to insert this style in a ResourceDictionary so you don't need to reference it everytime you use this control.
<Style TargetType="mc:MyMenuItem">
<!-- Style comes here -->
</Style>
Then you can acquire what you asked:
<mc:MyMenuItem MyHeaderText="Quit ERD Builder" MyShortcutText="Alt+F4" MyUriSource="/ERDBuilder;component/icons/bw/102-walk.png" />
I wish it can help you!
CoreStyle.xaml
The part from the Template / Style:
<Setter Property="Icon">
<Setter.Value>
<ctrl:Bitmap>
<ctrl:Bitmap.Source>
<!-- This doesnt work: --> <BitmapImage UriSource="{Binding Mode=OneWay, Path=MenuIcon, RelativeSource={RelativeSource FindAncestor, AncestorType=ctrl:MainMenuItem}}" />
<!-- This Still works fine: <BitmapImage UriSource="../Resources/Icons/16/page_add.png" />-->
</ctrl:Bitmap.Source>
</ctrl:Bitmap>
</Setter.Value>
</Setter>
MainMenuItem.cs
The Custom Control class that derives from MenuItem:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ErdBuilder.Shell.Controls
{
class MainMenuItem : MenuItem
{
public ICommand MenuCommand
{
get { return (ICommand) GetValue(MenuCommandProperty); }
set { SetValue(MenuCommandProperty, value); }
}
public static readonly DependencyProperty MenuCommandProperty = DependencyProperty.Register("MenuCommand", typeof(ICommand), typeof(MainMenuItem));
public string MenuText
{
get { return (string)GetValue(MenuTextProperty); }
set { SetValue(MenuTextProperty, value); }
}
public static readonly DependencyProperty MenuTextProperty = DependencyProperty.Register("MenuText", typeof(string), typeof(MainMenuItem));
public string MenuShortcut
{
get { return (string)GetValue(MenuShortcutProperty); }
set { SetValue(MenuShortcutProperty, value); }
}
public static readonly DependencyProperty MenuShortcutProperty = DependencyProperty.Register("MenuShortcut", typeof(string), typeof(MainMenuItem));
public string MenuIcon
{
get { return (string)GetValue(MenuIconProperty); }
set { SetValue(MenuIconProperty, value); }
}
public static readonly DependencyProperty MenuIconProperty = DependencyProperty.Register("MenuIcon", typeof(string), typeof(MainMenuItem));
}
}
I also tried this:
public BitmapImage MenuIcon
{
get { return new BitmapImage(new Uri((string)GetValue(MenuIconProperty))); }
set { SetValue(MenuIconProperty, value); }
}
public static readonly DependencyProperty MenuIconProperty = DependencyProperty.Register("MenuIcon", typeof(BitmapImage), typeof(MainMenuItem));
Shell.xaml
And finaly the Part where I try to use the new Control:
<ctrl:MainMenuItem x:Name="TestMenu"
MenuCommand="{x:Static ApplicationCommands.New}"
MenuText="New..."
MenuShortcut="Ctr+N"
MenuIcon="../Resources/Icons/16/page_add.png"/>

Issue binding Image Source dependency property

I have created a custom control for ImageButton as
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Local:ImageButton}">
<StackPanel Height="Auto" Orientation="Horizontal">
<Image Margin="0,0,3,0" Source="{Binding ImageSource}" />
<TextBlock Text="{TemplateBinding Content}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ImageButton class looks like
public class ImageButton : Button
{
public ImageButton() : base() { }
public ImageSource ImageSource
{
get { return base.GetValue(ImageSourceProperty) as ImageSource; }
set { base.SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageButton));
}
However I'm not able to bind the ImageSource to the image as:
(This code is in UI Folder and image is in Resource folder)
<Local:ImageButton x:Name="buttonBrowse1" Width="100" Margin="10,0,10,0"
Content="Browse ..." ImageSource="../Resources/BrowseFolder.bmp"/>
But if i take a simple image it gets displayed if same source is specified.
Can anyone tell me what shall be done?
You need to replace the Binding in your ControlTemplate by a TemplateBinding, just as you did for the Content property:
<Image Margin="0,0,3,0" Source="{TemplateBinding ImageSource}" />
Furthermore, the definition of your DependencyProperty is not correct. The string should read ImageSource instead of just Source:
DependencyProperty.Register("ImageSource", typeof(ImageSource), ...
I do not know whether/where this name conflict causes any problems, but at least it is highly recommended to use the exact name of the actual CLR property.
EDIT: You will also have to change the TargetType of your Style to your ImageButton:
<Style TargetType="{x:Type Local:ImageButton}">

Resources