I'm trying to design a button that has a dashed border all around and an image in the middle. The ideal hit test would be on the image itself, but not a requirement. My problem is that I can't get the click event to fire. It's probably a hit test problem, but I can't figure it out.
In addition to the obvious onClick on the button, I tried MouseEvents on the image, ButtonBase.Click on the Stackpanel, Border.InputBindings on the border .. I thought setting Background=Transparent would do it, but no go.
Here's the xaml:
<Button Grid.Row="0" Click="Button_Click_1">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="Transparent" Grid.Row="0" Margin="30,50" CornerRadius="10" BorderThickness="4">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeDashArray="4 2"
Stroke="#CEAC2D"
StrokeThickness="4"
RadiusX="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.TopRight}"
RadiusY="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.BottomLeft}"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" ButtonBase.Click="Button_Click_1">
<Button Height="30" Width="30" Content="Start"/> // just a test button to see if it works
<Image Source="/Images/uploadIcon.png" Height="180"/>
<TextBlock Margin="0,20,0,0" Foreground="#CEAC2D" Text="Drag Folder or Click to Browse" FontFamily="Lato" FontSize="27"
FontWeight="SemiBold" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
Why are you trying to set the whole thing as the button's template? If you only want the image bit actually clickable then set that as a button's control template and place it inside a regular visual tree:
<Border Background="Transparent" Grid.Row="0" Margin="30,50" CornerRadius="10" BorderThickness="4">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeDashArray="4 2"
Stroke="#CEAC2D"
StrokeThickness="4"
RadiusX="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.TopRight}"
RadiusY="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.BottomLeft}"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<Button Click="Button_Click_1" Cursor="Hand">
<Button.Template>
<ControlTemplate TargetType="Button">
<Image Source="/Images/uploadIcon.png" Height="180"/>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock Margin="0,20,0,0" Foreground="#CEAC2D" Text="Drag Folder or Click to Browse" FontFamily="Lato" FontSize="27"
FontWeight="SemiBold" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
Related
I am trying to show the validation error message of data grid row in a tooltip. Here is the code that works when I use the ToolTip property of the Grid control directly (wihtout styling):
<Grid Margin="0,-2,0,-2" ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" />
</Grid>
Now this shows the tooltip correctly. Everything is fine.
Problem:
As soon as I start styling the ToolTip separately, the binding stops working somehow. Here is the code that I am trying which does not work:
<Grid Margin="0,-2,0,-2">
<Ellipse x:Name="ErrorEllipse" StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center"/>
<Grid.ToolTip>
<ToolTip Background="Transparent" BorderBrush="Transparent" Height="Auto" Width="Auto">
<Border >
<TextBlock Text= "{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}"
MinHeight="20"
MinWidth="100"
Foreground="White"
Background="Red"/>
</Border>
</ToolTip>
</Grid.ToolTip>
</Grid>
What am I missing here and how can I achieve the proper binding? Probably its something basic but I have no idea...
You should style the ToolTip separately with a ControlTemplate.
<Style x:Key="ValidationToolTipStyle" TargetType="{x:Type ToolTip}">
<Setter Property="Background" Value="Transparent" />
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<Border >
<TextBlock
Text="{TemplateBinding Content}"
MinHeight="20"
MinWidth="100"
Foreground="White"
Background="Red"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then in your XAML, use the ToolTip like this:
<Grid Margin="0,-2,0,-2">
<Ellipse x:Name="ErrorEllipse"
StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock
Text="!"
FontSize="{TemplateBinding FontSize}"
FontWeight="Bold"
Foreground="White"
HorizontalAlignment="Center" />
<ToolTipService.ToolTip>
<ToolTip
Style="{StaticResource ValidationToolTipStyle}"
Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}, Path=(Validation.Errors)[0].ErrorContent}" />
</ToolTip>
</ToolTipService.ToolTip>
</Grid>
I hope this helps.
I would like to transform this button code into a template version and put it in a style xaml file:
<Button Background="Transparent" BorderBrush="Transparent" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="20" Foreground="White" Opacity="1">
<StackPanel Orientation="Horizontal">
<Rectangle Width="24" Height="24" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{iconPacks:PackIconMaterial Kind=Face, Width=24, Height=24}" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Margin="10 0 10 0" VerticalAlignment="Center" Text="John Doe" FontSize="24" FontWeight="Normal" FontFamily="Segoe UI Light" />
</StackPanel>
</Button>
I have this until now:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Name="ButtonGrid" RenderTransformOrigin="0.5,0.5">
<Rectangle Width="48" Height="48" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{Binding Path=(extensions:Icons.IconKind), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"/>
</Rectangle.OpacityMask>
</Rectangle>
<iconPacks:PackIconSimpleIcons x:Name="btnIcon" Kind="{Binding Path=(**extensions:Icons.IconKind**), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Width="48" Height="48" VerticalAlignment="Top" HorizontalAlignment="Center" Foreground="{TemplateBinding Foreground}" />
<TextBlock x:Name="tButton" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="{TemplateBinding Foreground}" FontWeight="Bold" Text="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
<StackPanel.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.0" CenterX="0.5" CenterY="0.5"/>
</StackPanel.RenderTransform>
</StackPanel>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
In a perfect world, the icon specified in the visual property should be set dynamically in the visual attribute of the template.
I came up with this solution but it doesn't work. Binding can only be done on DependencyProperty.
<VisualBrush Stretch="Fill" Visual="{iconPacks:PackIconMaterial Kind={Binding Path=(extensions:Icons.IconKind)}, Width=48, Height=48}"/>
Any idea how to do it? i'm not this good with template expressions :/
You could define a Template with a VisualBrush that binds to the Tag property of the Button:
<Style x:Key="IconStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Button}}">
<Rectangle Width="24" Height="24" Fill="{Binding Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{Binding Tag}" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Margin="10 0 10 0" VerticalAlignment="Center" Text="John Doe"
FontSize="24" FontWeight="Normal" FontFamily="Segoe UI Light" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...and then set the Tag property to an icon:
<Button Style="{StaticResource IconStyle}" Foreground="Green">
<Button.Tag>
<iconPacks:PackIconMaterial Kind="Face" Width="24" Height="24" />
</Button.Tag>
</Button>
I am not able to move buttons inside of a dock panel to the right, I tried few solutions, and after all I put them in stack panels and tried to move them to the right, but acctualy they wont move anywhere, here is how it looks:
And here is my code:
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="Black" Opacity="0.7">
<Expander.Header>
<DockPanel Height="50">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" DockPanel.Dock="Right"> <Button DockPanel.Dock="Right" Content="Test" Margin="0,0,28,0"/></StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" DockPanel.Dock="Left"> <TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Path=Name,StringFormat= Order Number:# {0}}" /></StackPanel>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
edit:
This above causes width on dock panel
<DockPanel Height="50" Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}">
<Button DockPanel.Dock="Right" Content="Test" Margin="0,0,28,0"/>
<TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Path=Name,StringFormat= Order Number:# {0}}" />
</DockPanel>
Try the following method. this works in my project
<DockPanel Height="50">
<grid DockPanel.Dock="Right">
<Button Content="Test" Margin="0,0,28,0"/>
</grid >
<grid DockPanel.Dock="Left">
<TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Path=Name,StringFormat= Order Number:# {0}}"/>
</grid>
</DockPanel>
Apply Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" to your DockPanel and see if this solves your problem.
I have six stack panel elements that are toggled all by a seperate toggle button which is what I need. However, when the user opens up one of the stack panels I would like to close all of the other ones and just show the one they have clicked on.
<Grid HorizontalAlignment="Left" Height="504" Margin="-1,1,0,0" VerticalAlignment="Top" Width="760">
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="boolConverter" />
</Grid.Resources>
<StackPanel HorizontalAlignment="Left" Height="505" VerticalAlignment="Top" Width="124" Background="#FF45B8F9" Margin="1,-1,0,0"/>
<StackPanel HorizontalAlignment="Left" Height="505" VerticalAlignment="Top" Width="124" Background="#FFF95545" Margin="636,0,0,-1" Visibility="{Binding ElementName=button, Path=IsChecked, Converter={StaticResource boolConverter}}"/>
<StackPanel HorizontalAlignment="Left" Height="505" VerticalAlignment="Top" Width="124" Background="#FFF9F945" Margin="507,-1,0,0" Visibility="{Binding ElementName=button_Copy, Path=IsChecked, Converter={StaticResource boolConverter}}"/>
<StackPanel HorizontalAlignment="Left" Height="505" VerticalAlignment="Top" Width="124" Background="#FF76F945" Margin="378,-1,0,0" Visibility="{Binding ElementName=button1, Path=IsChecked, Converter={StaticResource boolConverter}}"/>
<ToggleButton x:Name="button" Content="Green" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="105" Click="button_Click"/>
<ToggleButton x:Name="button_Copy" Content="Yellow" HorizontalAlignment="Left" Margin="10,55,0,0" VerticalAlignment="Top" Width="105" Click="button_Click"/>
<ToggleButton x:Name="button1" Content="Red" HorizontalAlignment="Left" Margin="10,114,0,0" VerticalAlignment="Top" Width="105"/>
</Grid>
Make a RadioButton custom template to display like an Expander:
<Style TargetType="{x:Type RadioButton}">
<Setter Property="GroupName" Value="MyToggleButtonGroupName"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Expander IsExpanded="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked}">
<ContentPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<RadioButton>
<StackPanel>...</StackPanel>
</RadioButton>
<RadioButton>
<StackPanel>...</StackPanel>
</RadioButton>
<RadioButton>
<StackPanel>...</StackPanel>
</RadioButton>
I'm trying to draw a dotted border around a button, however the border doesn't appear. Not sure what I'm doing wrong here, can you please help?
My Xaml code:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Grid Background="Ivory">
<Border Width="101" Height="31">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeThickness="1" Stroke="Red" StrokeDashArray="1 2"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
<Button Width="100" Height="30">
Focus Here</Button>
</Border>
</Grid>
</Page>
Note: The immediate issue was with border thickness, but still the dotted border is not appearing even after adding borderthickness.
Visual of the VisualBrush was not able to determine its size automatically so the VisualBrush was not drawn according to the size of the Border. Also note that you need to set same BorderThickness for Border as well as Rectangle. Have a look on the XAML below. Hope it will work good for you.
<Border x:Name="MyBorderedButton" Width="101" Height="31" BorderThickness="2" >
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeDashArray="4 2"
Stroke="Red"
StrokeThickness="2"
RadiusX="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.TopRight}"
RadiusY="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=CornerRadius.BottomLeft}"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
<Button>Focus Here</Button>
</Border>
Its working for me
In your solution, your rectangle has no size, so when it is drawn, there is nothing to draw, the solution is to inherit the size from the parent border:
<Border Width="101" Height="31" BorderThickness="1">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeThickness="1"
Stroke="Red"
StrokeDashArray="1 2"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}" />
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
<Button>
Focus Here
</Button>
</Border>