Callout style popup in WPF - c#

In my WPF application, I am trying to implement a Callout style Popup.
I got some reference but still could a good solution.
Please find the image what I am trying to implement.
It should be a popup window. The initial position should be indicating the parent button. But as it is a window so can be dragged from its location.
Please guide me.
Thanks.

You could use a Path:
<ToggleButton x:Name="toggleButton" Content="Button" Margin="100" />
<Popup IsOpen="{Binding IsChecked, ElementName=toggleButton}"
PlacementTarget="{Binding ElementName=toggleButton}"
Placement="Right"
StaysOpen="False"
AllowsTransparency="True"
VerticalOffset="-90">
<Grid>
<Border Background="Blue" BorderThickness="1" BorderBrush="Black"
Width="200" Height="200" Margin="24,0,0,0">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White">...</TextBlock>
</Border>
<Path StrokeThickness="1" Stroke="Black" Fill="Blue" VerticalAlignment="Center">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="25,0">
<PolyLineSegment Points="0,25 25,50"/>
<LineSegment Point="25,0" IsStroked="False"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
</Popup>

this should give you a general direction to start from:
<Button>
<Button.ToolTip>
<ToolTip Placement="Right">
<ToolTip.Style>
<Style TargetType="ToolTip">
<Setter Property="Background" Value="SkyBlue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<Grid>
<Polygon Points="10,0 0,5, 10,10" Fill="{TemplateBinding Background}" VerticalAlignment="Center"/>
<Border Margin="10,0,0,0" CornerRadius="5" Background="{TemplateBinding Background}" Name="button" Width="100">
<TextBlock>
<Run>This</Run>
<LineBreak/>
<Run>is</Run>
<LineBreak/>
<Run>an</Run>
<LineBreak/>
<Run> avesome tooltip</Run>
</TextBlock>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolTip.Style>
</ToolTip>
</Button.ToolTip>
</Button>

Related

How to set the rounded corners of TabItem to achieve the same effect as Google?

I have the code for the TabControl below. I want to achieve tab style similar to google chrome browser.
I want to make the bottom corners slightly rounder towards the pinkish background and not inwards.
How to set the rounded corners of TabItem to achieve the same effect as Google?
The resulting graph I have now:
Xmal:
<Window.Resources>
<SolidColorBrush x:Key="PrimaryBG" Color="#ad00ad"/>
<SolidColorBrush x:Key="Blueish" Color="#5252ff"/>
<SolidColorBrush x:Key="Greenish" Color="#005757"/>
<SolidColorBrush x:Key="Blackish" Color="#2e2e00"/>
<Style x:Key="{x:Type TabControl}" TargetType="{x:Type TabControl}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border BorderThickness="0,0,1,1" BorderBrush="#D0CEBF" Grid.Row="1">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter ContentSource="SelectedContent"/>
</Border>
</Border>
</Border>
<TabPanel Grid.Row="0" IsItemsHost="true" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TabItem">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<!--In order to click on the blank part of the TabItem can be successfully selected-->
<Border Background="Transparent" >
<Grid>
<Grid x:Name="g">
<Border CornerRadius="5,5,7,7" Background="{TemplateBinding Background}" Margin="0,0,0,-1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
</Grid>
<Border BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</Border>
<!--Add ControlTemplate.Triggers to change the background color of the selected TabItem.-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="{DynamicResource PrimaryBG}" Name="grid" >
<TabControl HorizontalAlignment="Center" HorizontalContentAlignment="Stretch" Margin="0,0,0,0"
Name="tabControl1" VerticalAlignment="Top" >
<TabItem Header="Dashboard" Name="tabItem1" Background="{DynamicResource Blueish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0">
<Border Background="#5252ff" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}">
<StackPanel>
<TextBox Width="200" Height="25"/>
<TextBox Width="200" Height="25"/>
</StackPanel>
</Border>
</TabItem>
<TabItem Header="Invoicing" Name="tabItem2" Background="{DynamicResource Greenish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0">
<Border Background="#005757" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}" >
<Button Width="80" Height="25"/>
</Border>
</TabItem>
<TabItem Header="Transactions" Name="tabItem3" Background="{DynamicResource Blackish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0" >
<Border Background="#2e2e00" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}" >
<ComboBox Width="300" Height="25"/>
</Border>
</TabItem>
</TabControl>
</Grid>
Edit:
Is it possible to give a path of the red line in the figure?
You can create any shape by Path and place it both sides of tab. For example, such Path would be as follows.
<Path Width="20" Height="40" Stretch="Uniform" Fill="Blue"
StrokeThickness="2" Stroke="Red"
Data="M 20,40 L 0,40 0,40 C 4,40 10,36 10,30 L 10,10 C 10,0 16,0 20,0"/>
You can flip it by <ScaleTransform ScaleX="-1"/>.
Edit:
Edited Path. You can draw outline by Stroke and leave a segment open by removing Z.

Show popup based on two properties (IsFocused, IsVisible)

I have popup error message box, it opens once the textbox is focused.
The issue when opening dialog window, if you click on the close button (on close I hide the window) the error message stays visible. I tried to add trigger to check the visibility but it didn't work. any idea?
XAML:
<ControlTemplate x:Key="errorToolTipTemplate">
<Grid>
<Border BorderBrush="#EF5B7C" BorderThickness="1" Background="#EF5B7C" Opacity="0.4" IsHitTestVisible="False" x:Name="errorBorder" />
<AdornedElementPlaceholder x:Name="placeholder" />
<Popup x:Name="popup" AllowsTransparency="True"
PopupAnimation="Fade"
Placement="Right"
VerticalOffset="-3"
PlacementTarget="{Binding ElementName=errorBorder}"
IsOpen="{Binding ElementName=placeholder, Path=AdornedElement.IsFocused, Mode=OneWay}">
<Popup.Style>
<Style TargetType="{x:Type Popup}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=errorBorder, Path=IsVisible, Mode=OneWay}" Value="False">
<Setter Property="IsOpen" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Popup.Style>
<DockPanel>
<Polygon VerticalAlignment="Center"
Points="0,5 5,0 5,10"
Fill="#EF5B7C"
Stretch="Fill" />
<Border Background="White" BorderBrush="#EF5B7C" BorderThickness="1" CornerRadius="4" Padding="2">
<DockPanel>
<Image Height="20" Width="20" VerticalAlignment="Center" Source="Images/C04_32.png" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{StaticResource errorBrush}"
FontWeight="Bold" Margin="2,0,0,0"
Text="{Binding ElementName=placeholder, Path=AdornedElement.ToolTip, Mode=OneWay}" />
</DockPanel>
</Border>
</DockPanel>
</Popup>
</Grid>
</ControlTemplate>
<!--Textbox style-->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource errorToolTipTemplate}" />
</Style>
Fixed this by adding triggers for the ControlTemplate.
I have add trigger with SourceTarget as the adorner, and TargetName as the popup, and changed the IsOpen property according to the other control visibility.
<ControlTemplate x:Key="errorToolTipTemplate">
<Grid>
<Border BorderBrush="#EF5B7C" BorderThickness="1" Background="#EF5B7C" Opacity="0.4" IsHitTestVisible="False" x:Name="errorBorder" />
<AdornedElementPlaceholder x:Name="placeholder" />
<Popup x:Name="popup" AllowsTransparency="True"
PopupAnimation="Fade"
Placement="Right"
VerticalOffset="-3"
PlacementTarget="{Binding ElementName=errorBorder}"
IsOpen="{Binding ElementName=placeholder, Path=AdornedElement.IsFocused, Mode=OneWay}">
<DockPanel>
<Polygon VerticalAlignment="Center"
Points="0,5 5,0 5,10"
Fill="#EF5B7C"
Stretch="Fill" />
<Border Background="White" BorderBrush="#EF5B7C" BorderThickness="1" CornerRadius="4" Padding="2">
<DockPanel>
<Image Height="20" Width="20" VerticalAlignment="Center" Source="Images/C04_32.png" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{StaticResource errorBrush}"
FontWeight="Bold" Margin="2,0,0,0"
Text="{Binding ElementName=placeholder, Path=AdornedElement.ToolTip, Mode=OneWay}" />
</DockPanel>
</Border>
</DockPanel>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="placeholder" Property="IsVisible" Value="False">
<Setter TargetName="popup" Property="IsOpen" Value="False" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

WPF Layering (ZIndex) of Thumb in Slider style

I have a custom Slider template and I want to place a content that sits above the Decrease and Repeat buttons but below the thumb. Ive tried adding zindex to the rectangle, which make it appear above everything, but I cannot figure out how to make the thumb appear above the rectangle
<!-- This is what I want to appear above the repeatbuttons but below the thumb -->
<Rectangle Height="8" Width="8" Fill="Yellow" Grid.Row="1" Panel.ZIndex="1" />
<Track x:Name="PART_Track" Grid.Row="1">
<Track.DecreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource DecreaseSliderRepeatButtonStyle}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource IncreaseSliderRepeatButtonStyle}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="Thumb" Style="{StaticResource HorizontalSliderThumbStyle}"/>
</Track.Thumb>
</Track>
Here is the relevant style for the thumb
<Style x:Key="HorizontalSliderThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="Panel.ZIndex" Value="100"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="#E6323232" CornerRadius="8" Height="16">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!--<TextBlock FontFamily="Arial" x:Name="tbPlaybackTime" Margin="7,0,7,0" Text="09:35:00" FontSize="10" Foreground="#eee" Background="Transparent" VerticalAlignment="Center"/>-->
<TextBlock FontFamily="Arial" x:Name="tbPlaybackTime" Margin="7,0,4,0" Text="09:35:00" FontSize="10" Foreground="#eee" Background="Transparent" VerticalAlignment="Center"/>
<Ellipse Grid.Column="1" Height="16" Width="16" Panel.ZIndex="10000">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,0" RadiusX="1" Center="0.5,0.5" >
<RadialGradientBrush.GradientStops>
<GradientStop Color="#ffffff" Offset="0.3" />
<GradientStop Color="#cccccc" Offset="0.8" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Ellipse.Fill>
<Ellipse.Effect>
<DropShadowEffect BlurRadius="3" Color="Black" Direction="270" Opacity="0.8" ShadowDepth="1" />
</Ellipse.Effect>
</Ellipse>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
here is a solution for placing your custom content over RepeatButton of a Slider
<Track Grid.Row="1"
x:Name="PART_Track">
<Track.Resources>
<ControlTemplate TargetType="RepeatButton"
x:Key="myRepeatbutton">
<Grid Background="Transparent">
<RepeatButton IsHitTestVisible="False"
Content="{TemplateBinding Content}"
Style="{TemplateBinding Style}" />
<Rectangle Height="8"
Width="8"
Fill="Yellow" />
</Grid>
</ControlTemplate>
</Track.Resources>
<Track.DecreaseRepeatButton>
<RepeatButton Command="Slider.DecreaseLarge"
Style="{StaticResource DecreaseSliderRepeatButtonStyle}"
Template="{StaticResource myRepeatbutton}" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource HorizontalSliderThumbStyle}"/>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Command="Slider.IncreaseLarge"
Style="{StaticResource IncreaseSliderRepeatButtonStyle}"
Template="{StaticResource myRepeatbutton}" />
</Track.IncreaseRepeatButton>
</Track>
Idea is to leverage the Template property of RepeatButton and by using a custom ControlTemplate apply the desired apperance
there are other possible workaround using opacity masks etc. but may be a bit complex to align properly. so if above does not work your expected way, we can opt for that too.

Custom combobox style

So after few days learning WPF im trying to make custom style for my ComboBox. I want to set border with content width to fill all unused space between border and drop down button. After I fix this I will start with drop down list with items.
Result:
Code:
<Style TargetType="ComboBox">
<Setter Property="Foreground" Value="Yellow"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<DockPanel>
<Border x:Name="bg" BorderBrush="Yellow" Background="HotPink" BorderThickness="1" CornerRadius="0" DockPanel.Dock="Left">
<ContentPresenter
Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="3,3,23,3"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</Border>
<Button x:Name="dropBtn" Width="20" DockPanel.Dock="Right" HorizontalAlignment="Right">
<Path VerticalAlignment="Center"
Width="10"
Height="8"
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
Stretch="Fill"
Fill="HotPink"/>
</Button>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Move button before border in your DockPanel so that it becomes last child of your panel.
Then set LastChildFill to True on DockPanel.
<DockPanel LastChildFill="True">
<Button x:Name="dropBtn" Width="20" DockPanel.Dock="Right"
HorizontalAlignment="Right">
<Path VerticalAlignment="Center"
Width="10"
Height="8"
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
Stretch="Fill"
Fill="HotPink"/>
</Button>
<Border x:Name="bg" BorderBrush="Yellow" Background="HotPink"
BorderThickness="1" CornerRadius="0" DockPanel.Dock="Left">
<ContentPresenter
Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="3,3,23,3"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</Border>
</DockPanel>
As per documentation of LastChildFill:
Gets or sets a value that indicates whether the last child element
within a DockPanel stretches to fill the remaining available space.

Defining the Name of a control in a Template in a subsequent event

I am trying to access the WebBrowser "wb" in the Img_ToolKitOpening event but it cannot be found.
Wb is defined in a Template
<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="#EEFFFFFF" BorderBrush="#FFCCCCCC" RenderTransformOrigin="1,1"
HorizontalAlignment="Center" VerticalAlignment="Center"
BorderThickness="1">
<Grid>
<Image x:Name="img" ToolTipService.Placement="Top"
Source="{Binding Path=ImageUri}" Height="64"
Stretch="Fill" Width="64" ToolTipOpening="img_ToolTipOpening">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" x:Name="scaleTrans"/>
</TransformGroup>
</Image.RenderTransform>
<Image.ToolTip>
<ToolTip BorderBrush="{x:Null}" Background="{x:Null}" Effect="{x:Null}"
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}"
HasDropShadow="False">
<Border Background="{x:Null}" VerticalAlignment="Center" Height="160" Margin="0" Width="100"
HorizontalAlignment="Center">
<Grid Background="{x:Null}">
<WebBrowser x:Name="wb"
Width="600" Height="600" />
</Grid>
</Border>
</ToolTip>
</Image.ToolTip>
</Image>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<ListBox x:Name="lbMovies" Height="92" Margin="81,0,94,26" ItemsPanel="{DynamicResource ItemsPanelTemplate1}"
ItemContainerStyle="{DynamicResource ListBoxItemStyle}" ItemsSource="{Binding}"
VerticalAlignment="Bottom" />
</Grid>
I am hoping to be able to perform wb.Navigate(#"c:\dump\bb.htm") to define the
HTML page to be displayed in the ToolTip when it is displayed.
Ifits defined in a template you could try to bind to the Source and then the event when the source is updated, if you cannot manage to access the WB in the codebehind.
Source="{Binding Path=WebBrowserUri}" SourceUpdated="wb_SourceUpdated"

Categories

Resources