Assistance designing a WPF control template - wpf

I am trying to design a template to be used with Bing Maps. I have started with the base template and torn a few bits out and added a few more bits, but I am making a bit of a mess of it!
What I am trying to acheive is a pushpin that has what appears to be a tooltip coming out of each side into which I can insert more information (though these are not actually tooltips; they are displayed permanantly based upon a binding property). Something like...
As you can see, I am not much of an artist and have not really gotten very far!
Can somebody help? What I would like is for the orange bars on each side of the pin to be able to contain text based upon a binding (and the bars should grow if required); whilst also being able to hide one or both bars depending on a binding (IsLeftTextVisible/IsRightTextVisible for example, the names do not matter I can change those later) or even if the bound field contains no text.
I would also really like for the orange bars to be a bit nicer; but if somebody can help me get to the point where I can display the text I (hopefully) should be able to take it from there.
Here is the code to produce what I have...
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF">
<ControlTemplate x:Key="PushpinTemplate"
TargetType="{x:Type m:Pushpin}">
<Grid Grid.Name="LayoutRoot"
FrameworkElement.Height="{TemplateBinding FrameworkElement.Height}"
FrameworkElement.Width="{TemplateBinding FrameworkElement.Width}">
<Canvas FrameworkElement.Height="35"
FrameworkElement.HorizontalAlignment="Left"
FrameworkElement.VerticalAlignment="Top"
FrameworkElement.Width="34">
<Path x:Name="CollectionTextPath"
Fill="{TemplateBinding Background}"
Data="M 0,20 H100 V-20 H-0"
Canvas.Left="20"
Stretch="Fill"
Width="100"
Height="18.905"
Canvas.Top="3.19"
RenderTransformOrigin="0.5,0.5" >
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="DeliveryTextPath"
Fill="{TemplateBinding Background}"
Data="M 0,20 H100 V-20 H-0"
Canvas.Left="-81"
Stretch="Fill"
Width="100"
Height="18.905"
Canvas.Top="4.19"
RenderTransformOrigin="0.5,0.5" >
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="-1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="Path_0"
Stretch="Fill"
StrokeLineJoin="Round"
Stroke="#FF333333"
Fill="#FFFFFFFF"
Data="F1M13.25,0.50001502C20.2917,0.50001502 26,6.2083602 26,13.25 26,17.817347 23.598524,21.823648 19.989363,24.075348 18.67861,25.105957 17.863953,27.531982 17.863953,27.531982L13.21736,39.595642 8.6221838,27.528591C8.6221838,27.528591 7.8198605,25.084908 6.6245556,24.145586 2.952121,21.907652 0.5,17.865215 0.5,13.25 0.5,6.2083602 6.2083402,0.50001502 13.25,0.50001502z"
UseLayoutRounding="False"
Height="39.694"
Width="26"
Canvas.Left="8.282"
Canvas.Top="0.001" />
<Ellipse Height="21"
Width="21"
Fill="{TemplateBinding Background}"
Canvas.Top="2.434"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Canvas.Left="10.806"
Stroke="{x:Null}" />
<Ellipse Height="18.905"
Width="18.905"
Canvas.Top="3.19"
Canvas.Left="11.911"
Stroke="{x:Null}">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#00FFFFFF"
Offset="0.438" />
<GradientStop Color="#6EFFFFFF"
Offset="0.987" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<UIElement.RenderTransform>
<TransformGroup>
<TranslateTransform TranslateTransform.X="-4" />
</TransformGroup>
</UIElement.RenderTransform>
</Canvas>
<Grid FrameworkElement.HorizontalAlignment="Center"
FrameworkElement.VerticalAlignment="Top"
FrameworkElement.Margin="0,2,0,0"
FrameworkElement.Height="22"
FrameworkElement.Width="21">
<ContentPresenter ContentPresenter.Content="{TemplateBinding ContentControl.Content}"
FrameworkElement.HorizontalAlignment="Center"
FrameworkElement.VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
<Style x:Key="{x:Type m:Pushpin}"
TargetType="{x:Type m:Pushpin}">
<Setter Property="Template"
Value="{StaticResource PushpinTemplate}" />
</Style>
</ResourceDictionary>
As you might gather, the canvas, grids and ellipses (the bits that look nice) are from the original template. I have then added the two Paths but I am now at a loss as to how to put text inside them (I could probably bind the text without problem if I had somewhere to put it).
I know this is a bit of an ask; but is there somebody who is a bit graphical and could move me forward a bit please. Any help would be appreciated.

I have extended the layout sufficiently.

Related

Why my UserControl using a Path as ControlTemplate is not properly clickable?

I created a class derived from UserControl, directly on code (without XAML), and defined a ControlTemplate in a ResourceDictionary. This control template is a pair of ellipses, as follows:
<ControlTemplate x:Key="MusclePositionControlTemplate" TargetType="{x:Type local:MusclePositionControl}">
<ControlTemplate.Resources>
<EllipseGeometry x:Key="bolinha" RadiusX="{StaticResource radius}" RadiusY="{StaticResource radius}">
<EllipseGeometry.Center>
<Point X="0" Y="{StaticResource distance}"/>
</EllipseGeometry.Center>
</EllipseGeometry>
</ControlTemplate.Resources>
<Path Fill="#9900ffff" StrokeThickness="1" Stroke="Black">
<Path.Data>
<GeometryGroup>
<StaticResource ResourceKey="bolinha"/>
<GeometryGroup>
<GeometryGroup.Transform>
<ScaleTransform ScaleY="-1"/>
</GeometryGroup.Transform>
<StaticResource ResourceKey="bolinha"/>
</GeometryGroup>
</GeometryGroup>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<RotateTransform Angle="{Binding Angle, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
<TranslateTransform
X="{Binding X, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Y="{Binding Y, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</ControlTemplate>
When I edit this template in Blend, I can select the path clicking on it, and it displays its outlines like this:
But when I add the actual control to a canvas, with its X, Y and Angle properties set to some value, the control renders itself fine, but its defining geometry keeps being that of a rectangle at the origin, and this affects hit testing (I cannot select at design time, or click at runtime, by clicking at the shape itself):
So my questions are:
How should I create a ControlTemplate using a Path as "root" visual element, so that the clickable area of the control is that Path?
Assuming a Path should not or could not be used as root visual for a ControlTemplate, how should I achieve the same end result?

Border.Background Effect

I have been trying Microsoft.Expression.Media.Effects to create a MonoChromeEffect on UIElements.
xmlns:e="http://schemas.microsoft.com/expression/2010/effects"
<Border.Effect>
<e: MonochromeEffect Color="Blue" />
</Border.Effect>
This works fine for any control with any Color.
My problem is when attempting to apply to an ImageBrush. (adding blue mono-tint to just the background).
<Border.Background >
<ImageBrush ImageSource="{Binding WaterMarkImage}"
Stretch="UniformToFill" Opacity=".34"
RenderOptions.BitmapScalingMode="HighQuality"
AlignmentX="Center" AlignmentY="Top" />
</Border.Background>
This will colorize all controls inside the Border - (including for instance - ListBoxItems to mono-blue).
Is there anyway to just affect just the ImageBrush - (not the list items - (keep them White)?
You may use a VisualBrush with an Image control instead of an ImageBrush and apply the effect to the Image:
<Border.Background>
<VisualBrush>
<VisualBrush.Visual>
<Image ImageSource="{Binding WaterMarkImage}"
Stretch="UniformToFill" Opacity=".34" ...>
<Image.Effect>
<e:MonochromeEffect Color="Blue"/>
</Image.Effect>
</Image>
</VisualBrush.Visual>
</VisualBrush>
</Border.Background>

Creating button with specific geometry XAML

Please can anyone suggest a solution of my problem.
Most "custom buttons" on different tutorials based on standard geometry forms (triangle, rectangle, circle etc.) anŠ² changed only their appearance.
I trying to create button with specific geometry and changed it on mouse event.
what I have:
I created style where diskribe
I created a polygon in the form of a rectangle with rounded corners (this is important)
I created style where described my custom button, and in main window i added the Style attribute:
<Button Width="40" Margin="5,0,5,-15" DockPanel.Dock="Right" HorizontalAlignment="Right" Background="{x:Null}" BorderBrush="{x:Null}" Height="40" Style="{StaticResource ResourceKey=PLCButtonStyle}"/>
this is how i described geometry:
</Style.Resources>
<Setter Property="Cursor" Value="Hand"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}" >
<Grid>
<MAIN:RoundedCornersPolygon Name="Border" Points="0,0 75,0 75,15 75,30 0,30 "Stretch="Fill"
StrokeThickness="1" ArcRoundness="5" UseRoundnessPercentage="False" Stroke="Black" IsClosed="True
<MAIN:RoundedCornersPolygon.Fill>
<RadialGradientBrush RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3" >
<GradientStop Color="lightgray" Offset="0" />
<GradientStop Color="black" Offset="1" />
</RadialGradientBrush>
</MAIN:RoundedCornersPolygon.Fill>
</SCADA:RoundedCornersPolygon>
I need to animate the transition of certain points of the polygon from one coordinate to another.
from Points="0,0 75,0 75,15 75,30 0,30 "
to Points="0,0 60,0 75,15 60,30 0,30 "
what i need to do for this?

Changing a Buttons Background in XAML?

How do I get the following XAML code to integrate into a buttons background. I've tried so many ways but I'm struggling to get it work. PS I'm new at XAML.
<Viewbox Width="55.247" Height="55.247"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Width="55.247" Height="55.247">
<Canvas>
<!-- button/circle -->
<Path StrokeThickness="1.0" Stroke="#ff335284" StrokeMiterLimit="1.0" Data="F1 M 54.747,27.624 C 54.747,42.603 42.603,54.747 27.624,54.747 C 12.644,54.747 0.500,42.603 0.500,27.624 C 0.500,12.644 12.644,0.500 27.624,0.500 C 42.603,0.500 54.747,12.644 54.747,27.624 Z">
<Path.Fill>
<RadialGradientBrush MappingMode="Absolute" GradientOrigin="392.717,-251.469" Center="392.717,-251.469" RadiusX="27.123" RadiusY="27.123">
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="#ff00aae4"/>
<GradientStop Offset="1.00" Color="#ff2463a7"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.Transform>
<MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,-365.093,-223.845" />
</RadialGradientBrush.Transform>
</RadialGradientBrush>
</Path.Fill>
</Path>
</Canvas>
</Canvas>
</Viewbox>
The following example replaces the standard Button Template with your design AND adds a content presenter so you can still set the content of the button.
<Button Content="OK" Width="75" Height="75">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Path StrokeThickness="1.0" Stroke="#ff335284" StrokeMiterLimit="1.0" Data="F1 M 54.747,27.624 C 54.747,42.603 42.603,54.747 27.624,54.747 C 12.644,54.747 0.500,42.603 0.500,27.624 C 0.500,12.644 12.644,0.500 27.624,0.500 C 42.603,0.500 54.747,12.644 54.747,27.624 Z">
<Path.Fill>
<RadialGradientBrush MappingMode="Absolute" GradientOrigin="392.717,-251.469" Center="392.717,-251.469" RadiusX="27.123" RadiusY="27.123">
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="#ff00aae4"/>
<GradientStop Offset="1.00" Color="#ff2463a7"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.Transform>
<MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,-365.093,-223.845" />
</RadialGradientBrush.Transform>
</RadialGradientBrush>
</Path.Fill>
</Path>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
Well you have multiple options to accomplish this. If you're literally just trying to put your Path in a button you can do it with minimal effort kind of like;
<Button Width="75" Height="75">
<!-- Embed our elements in a grid since Content can be set only once -->
<Grid>
<!-- Your Path -->
<Path StrokeThickness="1.0" Stroke="#ff335284" StrokeMiterLimit="1.0" Data="F1 M 54.747,27.624 C 54.747,42.603 42.603,54.747 27.624,54.747 C 12.644,54.747 0.500,42.603 0.500,27.624 C 0.500,12.644 12.644,0.500 27.624,0.500 C 42.603,0.500 54.747,12.644 54.747,27.624 Z">
<Path.Fill>
<RadialGradientBrush MappingMode="Absolute" GradientOrigin="392.717,-251.469" Center="392.717,-251.469" RadiusX="27.123" RadiusY="27.123">
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="#ff00aae4"/>
<GradientStop Offset="1.00" Color="#ff2463a7"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.Transform>
<MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,-365.093,-223.845" />
</RadialGradientBrush.Transform>
</RadialGradientBrush>
</Path.Fill>
</Path>
<!-- Your Button Text -->
<TextBlock Text="Button" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Button>
If you needed to get more technical / cleaner about it, you would just place it straight into a control template. Here's documentation on the WPF Button Control Template
Hope this helps, luckily there's also lots of tutorials out on the web for customizing a WPF button. If you want to elaborate on exactly what you'd like, like whether you're shooting for WPF or SL in particular (differences like VisualStateManager or Style Triggers) folks would likely be more useful. :)

Button with custom ControlTemplate sometimes misses clicks

My Button with a custom ControlTemplate does not respond to every click. I have no idea why, since it is totally random if the click works or not.
ControlTemplate:
<ControlTemplate x:Key="KreisPlus">
<Path Data="M74,37.5 C74,57.658393 57.658393,74 37.5,74 C17.341607,74 1,57.658393 1,37.5 C1,17.341607
17.341607,1 37.5,1 C57.658393,1 74,17.341607 74,37.5 z M32.113861,13.5 L43.386139,13.5 43.386139,
32.613861 62.5,32.613861 62.5,43.886139 43.386139,43.886139 43.386139,63 32.113861,63 32.113861,
43.886139 13,43.886139 13,32.613861 32.113861,32.613861 z"
Height="20" Stretch="Fill" Stroke="#FFD7D7D7" Width="20">
<Path.Fill>
<RadialGradientBrush>
<GradientStop Color="#FF1F71D5" />
<GradientStop Color="White" Offset="0.94" />
<GradientStop Color="#FF6499E0" Offset="0.78" />
</RadialGradientBrush>
</Path.Fill>
</Path>
</ControlTemplate>
<Button Click="Button_Click" Template="{StaticResource ResourceKey=KreisPlus}" />
just try this code sample and see is that what you expect?
<ControlTemplate x:Key="KreisPlus" TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent" >
<Path Data="M74,37.5 C74,57.658393 57.658393,74 37.5,74 C17.341607,74 1,57.658393 1,37.5 C1,17.341607 17.341607,1 37.5,1 C57.658393,1 74,17.341607 74,37.5 z M32.113861,13.5 L43.386139,13.5 43.386139,32.613861 62.5,32.613861 62.5,43.886139 43.386139,43.886139 43.386139,63 32.113861,63 32.113861,43.886139 13,43.886139 13,32.613861 32.113861,32.613861 z"
Height="20"
Stretch="Fill"
Stroke="#FFD7D7D7"
Width="20">
<Path.Fill>
<RadialGradientBrush>
<GradientStop Color="#FF1F71D5" />
<GradientStop Color="White"
Offset="0.94" />
<GradientStop Color="#FF6499E0"
Offset="0.78" />
</RadialGradientBrush>
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>
Now the path is inside the Grid and so it can respond to the click. This will take the entire area and only the path in the center. So if you click on the button anywhere even outside path will execute the click. If you don't want this and you want the path should respond to the click just change horizontal and vertical alignment as center
HorizontalAlignment="Center"
VerticalAlignment="Center"

Resources