wpf create image button - c#

my control template and style:
<ControlTemplate TargetType="{x:Type Button}" x:Key="ImageButtonTemplate">
<Image Source="..//..//images//ok.png"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"/>
</ControlTemplate>
<Style TargetType="{x:Type Button}" x:Key="ImageButton">
<Setter Property="Template" Value="{StaticResource ImageButtonTemplate}"/>
</Style>
<Button Style="{StaticResource ImageButton}" />
the button isn't visible ...
what am i missing ?
EDIT :
tried defining panel with height and width , button image is still not visible ..
little help .
<ControlTemplate TargetType="{x:Type Button}" x:Key="ImageButtonTemplate">
<Grid>
<Image Source="..//images//ok.png" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</Grid>
</ControlTemplate>
and aren't i suppose to put a in there ?
what am i doing wrong ?

You are not setting the width and height. Depending on the type of container you'll need it in order to be visible (if using stackpanel for example).
Here you have another related question that explains it.
WPF TriState Image Button
EDIT:
I create a new project and within the start window wrote:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<ControlTemplate TargetType="{x:Type Button}" x:Key="ImageButtonTemplate">
<Grid>
<Image Source="MB_0024_YT2.png" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</Grid>
</ControlTemplate>
<Style TargetType="{x:Type Button}" x:Key="ImageButton">
<Setter Property="Template" Value="{StaticResource ImageButtonTemplate}"/>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Button Style="{StaticResource ImageButton}" Width="120" Height="120" Click="Button_Click" />
</Grid>
</Window>
Now it's working. The button It's visible and within the event handler is working also.
Event Handler:
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
MessageBox.Show("Hello");
}

Related

Using {x: Bind} to bind to an XAML property, i.e. replacing {TemplateBinding XAMLProperty}

It is stated in MSDN that
Starting with Windows 10, version 1809, you can use the x:Bind markup extension anywhere you use TemplateBinding in a ControlTemplate.
However, when I try to replace TemplateBinding with {x:Bind} whilst defining the style of a custom control, as so,
<Style TargetType="local:PomodoroTimer" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:PomodoroTimer">
<Grid Width="300" Height="300" Background="{x:Bind Background}">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I get the following error: Unable to resolve symbol 'Background'. What am I missing?
x:Bind needs code-behind. (see here)
So, thanks to MainWindow.xaml.cs, this works:
<Window
x:Class="Bindings.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Bindings"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.Resources>
<Style
x:Key="CustomButtonStyle"
TargetType="Button">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
BorderBrush="{x:Bind BorderBrush, Mode=OneWay}"
BorderThickness="{x:Bind BorderThickness, Mode=OneWay}">
<ContentControl Content="{x:Bind Content, Mode=OneWay}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Grid.Resources>
<Button
BorderBrush="SkyBlue"
BorderThickness="1"
Content="Custom Button"
Style="{StaticResource CustomButtonStyle}" />
</Grid>
</Window>
For custom (templated) controls, I'd go with:
Text="{TemplateBinding Text}"
or
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
for TwoWay bindings.
If you want to do x:Bind inside the ControlTemplate, this answer might help.

MahApps MetroProgressBar does not work inside ControlTemplate

I would like to use MetroProgressBar in my UserControl.
<UserControl x:Class="WpfApplication7.UserControl1">
<StackPanel Background="#ccc">
<controls:MetroProgressBar IsIndeterminate="True"/>
</StackPanel>
</UserControl>
It works fine. But now I need to support external content in the user control.
So I created a new one "UserControl2" to demo:
<UserControl x:Class="WpfApplication7.UserControl2">
<UserControl.Resources>
<Style TargetType="{x:Type local:UserControl2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:UserControl2}">
<StackPanel Background="#ccc">
<controls:MetroProgressBar IsIndeterminate="True"/>
<!--<ContentPresenter/>-->
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
</UserControl>
Then I put the both controls to the form:
<StackPanel>
<local:UserControl1 Background="#ccc"/>
<local:UserControl2 Background="#ccc" Margin="0,6,0,0"/>
</StackPanel>
As result I see that UserControl2 does not show Progress Bar.
How can I fix it?
Note: In the designer UserControl2 is rendered as expected with progress bar.
In your style for UserControl2, set properties EllipseDiameter and EllipseOffset to some value (default is 4), as shown below:
<Style TargetType="{x:Type local:UserControl2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:UserControl2}">
<StackPanel Background="#ccc">
<controls:MetroProgressBar EllipseDiameter="12"
EllipseOffset="12"
IsIndeterminate="True"/>
<!--<ContentPresenter/>-->
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Force my tabitem to calcultate its width

I have the following style for my tabitems :
<Style x:Key="BoutonMenuHaut" TargetType="{x:Type TabItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Height="40" HorizontalAlignment="Stretch" CornerRadius="0" Name="border">
<Grid>
<ContentPresenterVerticalAlignment="Center"
HorizontalAlignment="Left"
TextBlock.Foreground="{StaticResource CouleurTexteBoutonsHaut}"
TextBlock.FontSize="{DynamicResource FontSizeBig}"
Name="textTab"
ContentSource="Header" Margin="10,0,60,0"
RecognizesAccessKey="True">
</ContentPresenter>
<Rectangle Height="2" x:Name="separation" Fill="Red" VerticalAlignment="Bottom" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see I bind the fontsize to a value defined like this :
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<sys:Double x:Key="FontSizeBig">16</sys:Double>
And in the window_sizechanged event I do this :
this.Resources["FontSizeBig"] = TextSizeFromResolution(12, height);
where height is the height of the screen.
But when I resize my window my tabitem doesn't resize itself and i'm not able to see all my tabs in the page anymore.
So my question is : How can I force the tabcontrol to resize the tabitems when the size changes ? (because the size of the text has changed so the tabitem's width should change too.
I've tried InvalidateMeasure, Update Layout... but I could not manage to make it work.
Could you help me ?
Thanks !
You could bind the width of the tabs to the ActualWidth of the tab control with a converter:
<Style TargetType="TabItem">
<Setter Property="Width" Value="{Binding
Path=ActualWidth, Converter={StaticResource YourConverter},
RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type TabControl}}}"/>
</Style>

WPF content control styling

I have a custom control which is basically a contentcontrol
public class PromoAlarmBox : ContentControl
{
static PromoAlarmBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PromoAlarmBox), new FrameworkPropertyMetadata(typeof(PromoAlarmBox)));
}
}
I add it to the containing user control
<controls:PromoAlarmBox Grid.Row="9" Grid.Column="1" />
If I add the style to the containing usercontrols resources everything works fine
<UserControl.Resources>
<Style TargetType="{x:Type controls:PromoAlarmBox}">
<Setter Property="ContentControl.ContentTemplate">
<Setter.Value>
<DataTemplate >
<Rectangle Fill="Blue" Stroke="Black" Height="20" Width="20"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
But if I add it to generic.xaml in the custom controls project , nothing is show
<Style TargetType="{x:Type local:PromoAlarmBox}">
<Setter Property="ContentControl.ContentTemplate">
<Setter.Value>
<DataTemplate >
<Rectangle Fill="Blue" Stroke="Black" Height="20" Width="20"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I know the style is applied as I have other controls in same project whos styles are defined in generic.xaml, Anyone have any ideas?
A simple static should do the trick...
static PromoAlarmBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PromoAlarmBox), new FrameworkPropertyMetadata(typeof(PromoAlarmBox)));
}
Although im not sure why there is a difference when you use a style as a local resource and when you use generic , this works for me
<Style TargetType="{x:Type local:PromoAlarmBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Rectangle VerticalAlignment="Stretch" Fill="Yellow" Stroke="Black" Height="20" Width="20"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How I can hide a Button inside a Control Template?

How can I set Visibility="Visible" for the Button inside the Control Template when the IsSendBtnVisible property in the code-behind is true?
Here's my WPF page:
<Page
x:Class="CardViewPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CardViewPage">
<Grid Name="content" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DocumentViewer Margin="0" Grid.Row="0" Name="documentViewer" />
</Grid>
</Page>
Here's my Custom Template for the document viewer on this page:
<Style TargetType="{x:Type DocumentViewer}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="Collapsed" />
...
</ControlTemplate>
</Setter>
...
</Style>
U need to declare DependancyProperty for ur DocumentViewer and use TemplateBinding in xaml ControlTemplate (UrProperty for example)
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="{TemplateBinding UrProperty}"
/>
...
</ControlTemplate>
I suggest you to use data triggers to achieve this...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25">
<Button.Style>
<Style>
<Setter Property="Button.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSendBtnVisible}" Value="True">
<Setter Property="Button.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Make sure to set visibility to collapsed in the style but not in the button properties..
Note: Binding for data trigger may change depending on your data context
Dima Martovoi,bathineni - thanks for replies.
Dima Martovoi, i think inherit from DocumentViewer is to hard for this small problem.
I tried to use variant with DataTrigger from bathineni's solution, but it's not works. Don't know, why.
Problem was solved using next binding:
<Button
Visibility="{Binding RelativeSource={RelativeSource AncestorType=Page},Path=SendToServerVisiblity}">
</Button>
where
public Visibility SendToServerVisiblity
{
get
{
if (IsOnlineMode)
return Visibility.Visible;
return Visibility.Collapsed;
}
}
in page code-behind

Categories

Resources