Wpf drop event not firing - c#

I have a user control simulating water mark text box.
I need to allow drop text files on the user control.
The PreviewDragEnter event works fine. This is the event where i want to verify that the file that been drag is actually a text file.
The problem is that the drop event never fires.
I want to catch the event when the user release the mouse button and decide to drop the file into the user control.
I think it got something to do with the multiple controls inside the user control and the hierarchy.
I really don't care which control will fire the drop event as long as it actually fire.
This is the xaml (the control i want to target the drop event is name 'txt')
<UserControl x:Class="CrumbSearch.CustomControls.package_watermark"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Height="45" Width="Auto"
FontFamily="B Yekan"
AllowDrop="true"
Grid.IsSharedSizeScope="True"
xmlns:wpfwatermarktextbox="clr-namespace:WPFWaterMarkTextBox;assembly=WPFWaterMarkTextBox">
<FrameworkElement.Resources>
<ResourceDictionary>
<FontFamily x:Key="simple_line_icon">/fonts/Simple-Line-Icons.ttf#simple-line-icons</FontFamily>
<Style x:Key="SimpleTextBox" TargetType="{x:Type TextBox}">
<Setter Property="AllowDrop" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Name="border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer Name="PART_ContentHost" Focusable="False" Margin="2,10,0,0"
AllowDrop="True"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsFocused" Value="True">
<Setter TargetName="border" Property="Border.BorderBrush" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SimplePasswordBox" TargetType="{x:Type PasswordBox}">
<Setter Property="AllowDrop" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border Name="border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<ScrollViewer Name="PART_ContentHost"
Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsFocused" Value="True">
<Setter TargetName="border" Property="Border.BorderBrush" Value="#00000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</FrameworkElement.Resources>
<Border Name="border" BorderThickness="0.5" CornerRadius="4" MouseEnter="border_MouseEnter"
MouseLeave="border_MouseLeave">
<FrameworkElement.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="White" />
<Setter Property="AllowDrop" Value="true" />
</Style>
</FrameworkElement.Style>
<Grid Name="MainGrid" PreviewMouseLeftButtonDown="MainGrid_PreviewMouseLeftButtonDown"
LostFocus="MainGrid_LostFocus">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Name="lbl2" Padding="5,0" FontSize="10" Content="Name"
Margin="0,5,0,0"
HorizontalAlignment="Left" Foreground="White" FlowDirection="LeftToRight"
VerticalAlignment="Top" Height="13" Grid.IsSharedSizeScope="True"
Opacity="0" Grid.Column="1" Background="{x:Null}" />
<TextBlock Name="lbl" Text="WaterMark" HorizontalAlignment="Left"
Foreground="#0EE7EC" FontSize="12"
Padding="5,5,5,0" FlowDirection="LeftToRight" FontFamily="Andalus"
TextWrapping="WrapWithOverflow" FontStyle="Italic"
Opacity="0.7" Grid.Column="1"
VerticalAlignment="Center" Background="{x:Null}" />
<TextBox Name="txt" Style="{DynamicResource SimpleTextBox}" FlowDirection="LeftToRight"
AllowDrop="true" Background="{x:Null}"
PreviewDragEnter="txt_PreviewDragEnter"
PreviewDrop="txt_PreviewDrop" Drop="txt_Drop"
TextWrapping="NoWrap" VerticalContentAlignment="Center" FontSize="14"
VerticalScrollBarVisibility="Disabled" MaxLines="1" FontWeight="Medium" Grid.Column="1"
BorderBrush="{x:Null}" TextChanged="TextBox_TextChanged" Foreground="White"
PreviewGotKeyboardFocus="txt_PreviewGotKeyboardFocus"
PreviewLostKeyboardFocus="txt_PreviewLostKeyboardFocus" />
<PasswordBox Name="pass" Style="{DynamicResource SimplePasswordBox}" FontSize="14"
VerticalContentAlignment="Center"
ScrollViewer.VerticalScrollBarVisibility="Disabled" Grid.Column="1"
Visibility="Collapsed" BorderBrush="{x:Null}"
Background="{x:Null}" PasswordChanged="PasswordBox_PasswordChanged" />
<Label Name="LblIcon" Padding="0" FontFamily="{DynamicResource simple_line_icon}"
VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
Foreground="#FF6A6A6A" FontSize="14" Background="{x:Null}" />
</Grid>
</Border>
</UserControl>

Found the answer here:
https://peteohanlon.wordpress.com/2009/09/28/textbox-dragdrop-in-wpf/
Apparently, Drag Drop into a TextBox in WPF doesn’t actually work. When you attempt to drag and drop an item into a TextBox, it refuses to cooperate and leaves the mouse cursor as the Drop denied cursor and you can’t drop into the field. (Incidentally, this behaviour also applies to RichTextBox and FlowDocument controls). The reason that you can’t drop into these fields, even if you set AllowDrop to true, is that these particular controls mark drag and drop events as handled, preventing you from handling them yourself.

Related

WPF How to change the IsSubmenuOpen color without disabling MenuItem dialogue box

I am trying to copy the IntelliJ Titlebar Menu in Windows as a learning exercise.
The default color changes of a WPF MenuItem seem to be:
Low Opacity blue background when "IsMouseOver" and not "IsSubmenuOpen"
Low Opacity blue background when "IsSubmenuOpen"
I would like to change this behavior to this (which can be observed in IntelliJ):
No color change when "IsMouseOver" and not "IsSubmenuOpen"
Dark blue background when "IsSubmenuOpen"
White foreground when "IsSubmenuOpen"
I have found code in this answer which is capable of doing this, but it also seems to disable the ability of the MenuItem to open its drop down box to reveal its children.
<Style x:Key="TitleBarMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Header}" Margin="35 5 10 5" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSubmenuOpen" Value="True">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#2675BF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I get these color changes without disabling the MenuItem functionality?
The problem you have there is that there's no popup for the sub menu. You're missing something like:
<Popup x:Name="Popup"
Placement="Right"
HorizontalOffset="-4"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border x:Name="SubmenuBorder"
SnapsToDevicePixels="True"
Background="{DynamicResource MenuPopupBrush}"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollViewer CanContentScroll="True"
Style="{StaticResource MenuScrollViewer}">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</ScrollViewer>
</Border>
</Popup>
Note that "IsItemsHost".
If you take a look at the templates for menu and menuitem you will notice it is very complicated stuff.
The approach I prefer is to work with content. You can put pretty much anything you like in a menuitem header.
One app I have does so with hard coded xaml. That's easier to understand than binding anyhow. Part of it looks like:
<MenuItem Header="_Layers" Style="{x:Null}">
<MenuItem>
<MenuItem.Header>
<CheckBox IsChecked="{Binding ShowBackground, Mode=TwoWay}">
_Background
</CheckBox>
</MenuItem.Header>
<MenuItem>
<MenuItem.Header>
<StackPanel Width="160">
<TextBlock Text="Opacity" />
<Slider Value="{Binding BackgroundOpacity, Mode=TwoWay}" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
</MenuItem>
<MenuItem>
<MenuItem.Header>
<CheckBox IsChecked="{Binding AppSettings.ShowElevationMap, Mode=TwoWay}">
_Elevation Map
</CheckBox>
</MenuItem.Header>
<MenuItem>
<MenuItem.Header>
<StackPanel Width="160">
<TextBlock Text="Opacity" />
<Slider
Value="{Binding AppSettings.ElevationOpacity, Mode=TwoWay}" />
</StackPanel>
</MenuItem.Header>
Layers is a top level menu item. These are templated different to their children. ( Did I mention menus are complicated ).
I offset the content so I don't need to worry about the icon column in the grid.
The styling I have might be useful to get you started.
You said this was a learning exercise so just doing it for you is presumably not exactly going to exercise your learning.
<ItemsPanelTemplate x:Key="MenuItemPanelTemplate">
<StackPanel Margin="-20,0,0,0" Background="White"/>
</ItemsPanelTemplate>
<Style TargetType="MenuItem" x:Key="MenuItemNoIcon">
<Setter Property="ItemsPanel" Value="{StaticResource MenuItemPanelTemplate}"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
<Style TargetType="{x:Type MenuItem}" x:Key="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{x:Static SystemColors.MenuBarBrush}"
SnapsToDevicePixels="True">
<Grid Margin="-1, 2, 0, 2">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MenuItemIconColumnGroup" Width="0"/>
<ColumnDefinition Width="0"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="0"/>
<ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"
Grid.Column="2" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="4" Margin="{TemplateBinding Padding}" Opacity="0.7" Text="{TemplateBinding InputGestureText}" VerticalAlignment="Center"/>
<Path x:Name="RightArrow" Grid.Column="5" Width="10" Data="M0,0L4,3.5 0,7z" Fill="#FF212121" Margin="8,0,2,0" VerticalAlignment="Center"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-2"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right" VerticalOffset="-3">
<Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Background="#FFF0F0F0" Padding="2">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="Transparent"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
<Setter Property="Fill" TargetName="RightArrow" Value="#FF707070"/>
</Trigger>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Visibility" TargetName="RightArrow" Value="Collapsed"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

In WPF Only icon of a button is click able not whole of the button

I am trying to make a costume button in c# wpf. I used material design themes for inserting an icon inside the button but when I run the program, only the icon inside the button is click able not the whole button. what should I do to fix this?
I did this for button style:
<Application.Resources>
<Style x:Key="MyButton" TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="border" BorderThickness="0" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
here is the button:
<Button x:Name="btnClose" Style="{StaticResource MyButton}" Width="30" Height="30" Padding="0" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Gray" Margin="10 0" Click="btnClose_Click">
<materialDesign:PackIcon Kind="Power" Height="30" Width="30"></materialDesign:PackIcon>
</Button>
Set the Background property to a Brush like for example Transparent instead of setting it to {x:Null}:
<Button x:Name="btnClose" Style="{StaticResource MyButton}" Width="30" Height="30" Padding="0"
Background="Transparent" BorderBrush="{x:Null}" Foreground="Gray" Margin="10 0" Click="btnClose_Click">
<materialDesign:PackIcon Kind="Power" Height="30" Width="30"></materialDesign:PackIcon>
</Button>

Round combobox style wpf

I wish to construct a custom round ComboBox:
This is the style I'm using:
<Style x:Key="ComboBoxButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="White" x:Name="border" CornerRadius="0,5,5,0" BorderThickness="0,2,2,2" BorderBrush="Black">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border CornerRadius="5,0,0,5" BorderThickness="2,2,0,2" Background="{TemplateBinding Background}" BorderBrush="Black">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RoundComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MaxWidth="18"/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox" IsEnabled="False" Style="{StaticResource ComboBoxTextBoxStyle}" Padding="5,0,0,0" Height="{TemplateBinding Height}"/>
<ToggleButton Grid.Column="1" Margin="0" Height="{TemplateBinding Height}" Style="{StaticResource ComboBoxButtonStyle}" Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
<Path Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z" Fill="DodgerBlue" />
</ToggleButton>
<ContentPresenter Grid.Column="0" Name="ContentSite" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<Popup Grid.Column="0" Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="False" Focusable="False" PopupAnimation="Slide">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}" >
<Border x:Name="DropDownBorder" BorderThickness="1" CornerRadius="5" Background="White" BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The thing is that when I use this style, in order to open the ComboBox and see all the items, I have to click the arrow ToggleButton. I can't click the text, or the TexBox.
So, in order to change that, I edited the 'RoundComboboxStyle' that way:
<Style x:Key="RoundComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid Grid.IsSharedSizeScope="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="ComboBoxButton"/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox" Grid.Column="1" IsReadOnly="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ComboBoxTextBoxStyle}" Margin="{TemplateBinding Padding}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ToggleButton Background="{x:Null}" Grid.ColumnSpan="3" Style="{StaticResource ComboBoxButtonStyle}" Opacity="0" Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
<ContentPresenter Grid.Column="1" Name="ContentSite" Content="{TemplateBinding SelectionBoxItem}" VerticalAlignment="Center"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" HorizontalAlignment="Center"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Margin="5,0,0,0"/>
<Popup Grid.Column="1" Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="False" Focusable="False" PopupAnimation="Slide">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" BorderThickness="1" CornerRadius="5" Background="White" BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now, I can click the TextBox to open the ComboBox items list, but I cannot click on the text itself (that does not open the items list).
Also, the ComboBox now looks like this:
Is there a way to combine the two looks and also make the ComboBox behave like a style-less one, in which I can click anywhere on the ComboBox in order to open the list of items?
Please change the following:
<Style x:Key="RoundComboBoxStyle" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
The based on property will maintain the basic style of the combobox i.e. clicking on content, etc.
Well, searched and investigated, and finally found the correct configuration for the style to work. Posting the code:
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
<Border x:Name="PART_ContentHost" BorderThickness="1" Focusable="False" Background="{TemplateBinding Background}" />
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="10,10,10,10" Background="White" BorderBrush="Black" BorderThickness="2" />
<Path x:Name="Arrow" Grid.Column="1" Fill="DodgerBlue" HorizontalAlignment="Center" VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="LightSteelBlue" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="LightSteelBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="RoundComboBoxTemplate" TargetType="{x:Type ComboBox}">
<Grid>
<Rectangle Stroke="White" RadiusX="10" RadiusY="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto"
x:Name="Rectangle" Fill="White" />
<ToggleButton Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Height="{TemplateBinding Height}" Focusable="False"
ClickMode="Press" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
</ToggleButton>
<TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" Template="{StaticResource ComboBoxTextBox}" Margin="3,3,23,3"
Focusable="True" Background="Transparent" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}"/>
<ContentPresenter Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" Margin="3,3,23,3"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" VerticalAlignment="Center"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" HorizontalAlignment="Center" />
<Popup Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" Background="White" BorderThickness="1" BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger Property="IsGrouping" Value="True">
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="True">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
</Trigger>
<Trigger Property="IsEditable" Value="True">
<Setter Property="IsTabStop" Value="False"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

Switching Focus from Grid/TextBlock to TextBox

I am making a numeric text box, which can also contain various additional symbols to denote if the data contained in the control is a percentile, radius, etc. For this I have a grid with a text box to the left and a TextBlock to the right. Here is a picture:
The problem that I am having with this, however, is that if the mouse is over the textblock, and I click, I cannot get the TextBox to gain focus. I have tried _textbox.Focus() on mouse down of the textblock, as well as on the parent grid. This did not work.
After some googling, I read that I could put FocusManager.FocusedElement="{Binding ElementName=_textbox}" on the parent Grid, and this would solve my problem. However, even with this, the Textbox still does not gain focus. I've even tried making neither the textbox or textblock hit-testable, and instead use the grid itself as a hit test, but even with this, the textbox itself still will not gain focus. I'm at a loss of what to do here. Does anyone know how I can make the textbox gain focus, when either the parent grid is clicked, or the textblock is clicked? Or Both?
Here is my XAML:
<UserControl
x:Class="VoidwalkerEngine.Editor.Controls.NumericTextBox"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="32"
d:DesignWidth="80"
BorderThickness="0"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ButtonTop" TargetType="Button">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="ButtonBackground"
Background="{DynamicResource Voidwalker_Gradient_Button}"
BorderBrush="{DynamicResource Voidwalker_Brush_Border}"
BorderThickness="1,0,0,1"
CornerRadius="0,2,0,0">
<ContentPresenter
x:Name="contentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonBackground" Property="Background" Value="{DynamicResource Voidwalker_Gradient_ButtonPressed}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonBackground" Property="Background" Value="{DynamicResource VoidwalkerButtonBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtonBottom" TargetType="Button">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="ButtonBackground"
Background="{DynamicResource Voidwalker_Gradient_Button}"
BorderBrush="{DynamicResource Voidwalker_Brush_Border}"
BorderThickness="1,1,0,0"
CornerRadius="0,0,2,0">
<ContentPresenter
x:Name="contentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonBackground" Property="Background" Value="{DynamicResource Voidwalker_Gradient_ButtonPressed}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonBackground" Property="Background" Value="{DynamicResource VoidwalkerButtonBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Border
Background="{DynamicResource Voidwalker_Brush_ContextArea}"
BorderBrush="{DynamicResource Voidwalker_Brush_Border}"
BorderThickness="1"
CornerRadius="3">
<Grid Focusable="False">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="23" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
BorderThickness="0"
CornerRadius="2,0,0,2">
<Grid
Cursor="IBeam"
FocusManager.FocusedElement="{Binding ElementName=_textbox}"
MouseDown="_backAreaGrid_OnClick">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<TextBox
x:Name="_textbox"
Grid.Column="0"
Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Background="{DynamicResource VoidwalkerContextBrush}"
BorderThickness="0"
CommandManager.PreviewExecuted="_numericDisplayTextBox_OnPreviewExecuted"
Foreground="{DynamicResource Voidwalker_Brush_ActiveTextForeground}"
GotFocus="_textbox_OnGotFocus"
LostFocus="_numericDisplayTextBox_OnLostFocus"
MouseDoubleClick="_textbox_OnMouseDoubleClick"
PreviewKeyDown="_numericDisplayTextBox_OnPreviewKeyDown"
PreviewMouseWheel="_numericDisplayTextBox_OnPreviewMouseWheel"
Text="0"
TextAlignment="Right"
TextChanged="_numericDisplayTextBox_OnTextChanged" />
<TextBlock
x:Name="OperatorDisplayTextBox"
Grid.Column="1"
VerticalAlignment="Center"
Cursor="IBeam"
Foreground="{DynamicResource Voidwalker_Brush_ActiveTextForeground}"
Text="%" />
</Grid>
</Border>
<Button
Grid.Row="0"
Grid.Column="1"
BorderThickness="1,0,0,0"
Click="Increment_Button_OnClick"
Style="{DynamicResource ButtonTop}">
<Path Data="M 1,4.5 L 4.5,1 L 8,4.5" Fill="{DynamicResource Voidwalker_Brush_ActiveTextForeground}" />
</Button>
<Button
Grid.Row="1"
Grid.Column="1"
BorderThickness="1,0,0,0"
Click="Decrement_Button_OnClick"
Style="{DynamicResource ButtonBottom}">
<Path
ClipToBounds="True"
Data="M 1,1.5 L 4.5,5 L 8,1.5"
Fill="{DynamicResource Voidwalker_Brush_ActiveTextForeground}" />
</Button>
</Grid>
</Border>
</UserControl>
I figured it out after reading this page. I don't know why this code works...like, at all actually. It seems like i'm using a backwards, roundabout way into the control to avoid threading issues... isn't that what the Dispatcher is for? So is it safe to assume that a .Focus() method does nothing unless it's used like below? It's whatever, I guess, less hair pulling now, and more coding. Here is the code that worked for me. All I had to do was add this to the parent grid's MouseDown event:
private void _backAreaGrid_OnMouseDown(object sender, MouseButtonEventArgs e)
{
Dispatcher.BeginInvoke(
DispatcherPriority.ContextIdle,
new Action(delegate
{
_textbox.Focus();
}));
}
The textbox gains focus regardless of what I click on in the surrounding grid.

How to change a background of a single tab item header in WPF?

I've been stylizing a TabControl in WPF XAML (.NET 4), all i can do is style a tab based on triggers or identically style them all. Is there any way that only the first tab is stylized different while the other tabs are stylized different than the first tab but the same as each other (a.k.a using the Tab Index to stylize a TabItem).
Thank you.
You can use AlternationCount and AlternationIndex:
<TabControl AlternationCount="{Binding Path=Items.Count,RelativeSource={RelativeSource Self}}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex"
Value="0"> <!-- First item -->
<Setter Property="FontWeight"
Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</TabControl.ItemContainerStyle>
<TabItem Header="First"/>
<TabItem Header="Second"/>
<TabItem Header="Third"/>
<TabItem Header="Fourth"/>
</TabControl>
If you want to change the background color of just selected tab item then use that kind of style and apply that style to tab Item.
<Style TargetType="{x:Type TabItem}" x:Key="TabItemStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Background="Red" BorderBrush="#FF1467AF"
BorderThickness="1"
Margin="0,0,5,0" CornerRadius="8,8,0,0" SnapsToDevicePixels="True">
<TextBlock FontFamily="Arial" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center" Name="TextBlock" Foreground="White">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2"/>
</TextBlock>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But if you want to just change the background color of First tab item then define two styles and apply one to first tab item and second one to other
Style for tab item 1:
<Style TargetType="{x:Type TabItem}" x:Key="TabItemStyleForFirst">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Background="Red" BorderBrush="#FF1467AF"
BorderThickness="1"
Margin="0,0,5,0" CornerRadius="8,8,0,0" SnapsToDevicePixels="True">
<TextBlock FontFamily="Arial" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center" Name="TextBlock" Foreground="White">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2"/>
</TextBlock>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Style for other tab items:
<Style TargetType="{x:Type TabItem}" x:Key="TabItemStyleForOther">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Background="Yellow" BorderBrush="#FF1467AF"
BorderThickness="1"
Margin="0,0,5,0" CornerRadius="8,8,0,0" SnapsToDevicePixels="True">
<TextBlock FontFamily="Arial" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center" Name="TextBlock" Foreground="White">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2"/>
</TextBlock>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Categories