WPF scrollbar location - wpf

I have a Stackpanel inside of a TabItem that is part of a TabControl. As things get added to the StackPanel, I have a custom vertical ScrollBar appear. Currently its appearing inside the TabItem control "on top of" the stack panel. I want to move the scroll bar's location to outside of the TabControl altogether. I've tried to do some things with margin, but as the ScrollBar gets pushed outside the edge of the TabControl, it just gets clipped, and no amount of me messing with zindex has resulted in any success. Any help would be appreciative. - Leif
<TabItem Name="tabItem1" Background="{x:Null}" BorderBrush="#FF48D6EE" IsSelected="True">
<TabItem.Template>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Tab1" Margin="0,0,0,0" BorderBrush="#FF002648" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" Color="#FF3Ed3F4" Opacity=".5" BlurRadius="2"/>
</Border.Effect>
</Border>
<HeaderedContentControl Name="TabHeaderText"
TextBlock.FontFamily="Aharoni"
TextBlock.FontWeight="Bold"
TextBlock.Foreground="#FF214c6d"
TextBlock.FontSize="18"
Header="Tab1"
Margin="10,1,10,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Tab1" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#FF000a13" Offset="0" />
<GradientStop Color="#FF06335c" Offset="0.5" />
<GradientStop Color="#FF33bbdb" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="Tab1" Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="#FF3ccbee" Opacity="1" BlurRadius="5"/>
</Setter.Value>
</Setter>
<Setter TargetName="Tab1" Property="BorderBrush" Value="#FF48d6ed"/>
<Setter TargetName="Tab1" Property="BorderThickness" Value="1,0,1,1" />
<Setter TargetName="Tab1" Property="Header">
<Setter.Value>
<custom:OutlinedText FontSize="18"
FontFamily="Aharoni"
FontWeight="ExtraBold"
Fill="Black"
Stroke="#ff3bb1db"
StrokeThickness=".75"
Text="Tab1"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TabItem.Template>
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Template="{StaticResource ScrollViewerControlTemplate}">
<StackPanel Name="panelTab1" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</ScrollViewer>
</TabItem>

We ran into a similar issue. What we discovered is that WPF does not draw things with negative margins, when they are clipped. Clipping comes into play when one of the elements that contains the TabItem control has a MinHeight set, and the window shrinks below the MinHeight. By default the scroll bar uses a negative margin for the PART_VerticalScrollBar.
The solution is to make sure that you do not have MinHeight set on any of the containers that may contain your TabItem. If you need to use MinHeight, set it on the top level view.
The Snoop tool is very helpful for debugging WPF layout issues.
http://snoopwpf.codeplex.com/

Related

WPF RadioButton/ToggleButton styling

I would like to mimic a style for a group of ToggleButtons as in the below image. Only one of the buttons can be "Checked" at any time.
My question is related to styling:
I'd like to have rounded corners on the leftmost button and the rightmost button as in the image but if there is a button between (like in the image), that should not have rounded corners. Sometimes there might only be two buttons to toggle.
I need style for different states: "Normal/Unchecked", "Mouseover", "Pressed" and "Checked" at the minimum.
The current control I am using for this is done like this:
<StackPanel Orientation="Horizontal" >
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="All" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Geolocated" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Non Geolocated" Padding="12,8,12,8" GroupName="View" />
</StackPanel>
In the StackPanel Resources I am trying to set Style for ToggleButton but I'm pretty lost how to achieve the result as in the image above.
This may not be the easiest/best approach, but I took a stab at knocking up some ControlTemplates using Kaxaml, to produce something that looks like this:
You could store these templates in a ResourceDictionary and apply them when required, or use them if you were building your button list on the fly.
I actually created three slightly different styles, one for the left and right buttons, and one for the middle (you may be able to simplify this with extending/inheriting styles). Some repeated code omitted.
<Grid>
<Grid.Resources>
<!-- Brushes for colours/backgrounds -->
<SolidColorBrush x:Key="FontBrush" Color="#DDDDDD"/>
<LinearGradientBrush x:Key="BgBrush1" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#888888"/>
<GradientStop Offset="1" Color="#222222"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="BorderBrush1" Color="#333333"/>
<LinearGradientBrush x:Key="CheckedBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#555555"/>
<GradientStop Offset="1" Color="#111111"/>
</LinearGradientBrush>
<!-- Left Button Template -->
<ControlTemplate x:Key="ToggleButtonLeft" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="5,0,0,5">
<ContentPresenter
HorizontalAlignment="Center"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
TextBlock.FontWeight="Bold"
TextBlock.Foreground="{StaticResource FontBrush}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="#808080"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Middle Button(s) Template -->
<ControlTemplate x:Key="ToggleButtonMid" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="0,1,0,1"
CornerRadius="0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
<!-- Right Button Template -->
<ControlTemplate x:Key="ToggleButtonRight" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="0, 5, 5, 0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
</Grid.Resources>
<!-- Example Usage -->
<Grid Background="#555555">
<StackPanel Height="25" Orientation="Horizontal" Margin="5">
<RadioButton Content="All" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonLeft}"/>
<RadioButton Content="Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonMid}"/>
<RadioButton Content="Non Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonRight}"/>
</StackPanel>
</Grid>
</Grid>
You would have to add additional Triggers etc. for the IsPressed state, and any others required (e.g IsEnabled).

Issue with arorner when doing validation on a TextBox control

I am validating a TextBox control for a particular range. If user enter a value out of range, an Adorner control as shown in the image above is shown.
My problem is the control is cut beyond the window size. How do I place the red adorner above the window even though the window size is smaller as above.
Below is the code I have used for a ControlTemplate and Style:
<ControlTemplate x:Key="validationTemplate">
<DockPanel LastChildFill="True">
<TextBlock Name="ErrorText" DockPanel.Dock="Bottom" Foreground="White"
FontSize="12" Padding="7" FontFamily="Trebuchet MS"
Margin="5,5,0,0"
TextWrapping="Wrap"
Text="{Binding [0].ErrorContent}" >
<TextBlock.Background>
<SolidColorBrush Color="Red" Opacity="0.95"></SolidColorBrush>
</TextBlock.Background>
</TextBlock>
<AdornedElementPlaceholder Name="ErrorTextBox" />
</DockPanel>
</ControlTemplate>
<Style x:Key="ValidationStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Red" ShadowDepth="5" Direction="135" Opacity="0.5"></DropShadowEffect>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Please help.
Well, I am not aware that Adorners can be rendered outside of the window, so for your question, you can't place Adorner outside of window.
However, popup is usually used, when you need behaviour like that. Just wrap everything into Popup element, and see if it helps.

Override ToggleButton Style

I have a ToggleButton in my window and styled in my ResourceDictionary. The reason why it's in the ResourceDictionary is because I have several or more ToggleButton soon which has to have the same look.
<Style x:Key="Standardbutton" TargetType="{x:Type ToggleButton}">
<Setter Property="FontSize" Value="18" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/Standard_Button_Normal.png" />
</Setter.Value>
</Setter>
<Setter Property="Height" Value="56" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Name="border" BorderThickness="0" Padding="0,0" BorderBrush="DarkGray" CornerRadius="0" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" Name="content" Margin="15,0,0,0"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/Standard_Button_Pressed.png" />
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF9CE7B" Offset="0"/>
<GradientStop Color="#FFE88C41" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now this ToggleButton style has a default background and also when "IsChecked" is true, it will have different background (as you can see on my XAML code above).
Now these toggle buttons has to have icon + text combined, like what I did here (sorry for my lame XAML code)
<ToggleButton Style="{DynamicResource Standardbutton}" Margin="0,0,0,4">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/scan_26x26.png" />
<TextBlock Text="Scan"/>
</StackPanel>
</ToggleButton>
The question is, how can I have a different icon when the ToggleButton is checked (IsChecked=True)?
Here are some images that might help you to understand the question
Normal ToggleButton Style
IsChecked=True Style
My design goal is to have a different icon when IsChecked=True
Add both images to the control template, and bind their Visibility property to the IsChecked property (use an IValueConverter to convert from true/false to the appropriate Visibility enum value).
<ToggleButton Style="{DynamicResource Standardbutton}" Margin="0,0,0,4">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/scan_26x26.png"
Visibility="{Binding
RelativeSource={RelativeSource AncestorType=ToggleButton},
Path=IsChecked,
Converter={StaticResource BoolToVisibleConverter}}" />
<Image Source="Resources/anotherimage.png"
Visibility="{Binding
RelativeSource={RelativeSource AncestorType=ToggleButton},
Path=IsChecked,
Converter={StaticResource BoolToCollapsedConverter}}" />
<TextBlock Text="Scan"/>
</StackPanel>
</ToggleButton>
I used two converters BoolToVisibleConverter and BoolToCollapsedConverter, but you could also use a ConverterParameter to accomplish the same thing.

WPF: LinearGradientBrush with Alpha not works in a Popup control?

I want to create a custom WPF dropdown menu, so I created a User control which contains a ToggleButton and a Popup control. The popup appears when I click on the button.
Now I want to add a mouse hover effect on the menu items in the popup: but the LinearGradientBrush is not working with alpha channels:
<UserControl.Resources>
...
<Style x:Key="SubMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
<Rectangle x:Name="rectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" />
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="rectangle" Value="#30000000"/>
<Setter Property="Fill" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="#10000000" Offset="0"/>
<GradientStop Color="#10FFFFFF" Offset="1"/>
<!-- Not works... -->
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" TargetName="text" Value="#FF9A9A9A"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Controls:ToggleImageButton Style="{DynamicResource ArrowMenuStyle}" x:Name="imageButton" Height="21" />
<Popup x:Name="popup" PlacementTarget="{Binding ElementName=imageButton}" Placement="Bottom" StaysOpen="False" IsOpen="{Binding ElementName=imageButton, Path=IsChecked}">
<ItemsControl ItemsSource="{Binding MenuCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Command="{Binding Command}" Background="{Binding ElementName=popupMenuControl, Path=MenuBackground}" Foreground="{Binding ElementName=popupMenuControl, Path=MenuForeground}" Click="MenuItem_Click" Style="{StaticResource SubMenuItemStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Popup>
</Grid>
When I set the GradientBrush to this, everything works fine:
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Yellow" Offset="1"/>
</LinearGradientBrush>
But it seems the Alpha channel breaks the whole thing, and what I see is a black rectangle.
...Any idea?
If I put the MenuItems inside a Menu container, the Menu overrides my styles...
Thanks in advance!
have you set AllowsTransparency to true?

DataGridCloumnHeaderCheckbox style

I am using WPF datagrid. Using the following style I am applying checkbox to one of the columheader.
<Style x:Key="TestDataColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<CheckBox x:Name="chkbxCheckAll" VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Path=CheckAll, Mode=TwoWay, ElementName=TestDataScreen}" Click="chkbxCheckAll_Click">
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Control.Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="1" Color="#FFC2E3F6" />
<GradientStop Offset="0.53" Color="#FFF1FBFD" />
<GradientStop Color="#FFF2FAFD" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Control.BorderBrush" Value="#FFDADADA" />
<Setter Property="Control.BorderThickness" Value="1,0,1,1" />
<Setter Property="Control.Height" Value="26" />
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
</Style>
The problem I am facing is, I can see the checkbox in columnheader but columnheader background color is not changed.
Try adding a border around the checkbox like this
<Border Background="{TemplateBinding Background}">
<CheckBox x:Name="chkbxCheckAll" VerticalAlignment="Center"
HorizontalAlignment="Center"
IsChecked="{Binding Path=CheckAll, Mode=TwoWay, ElementName=TestDataScreen}"
Click="chkbxCheckAll_Click">
</CheckBox>
</Border>
Edit:
If you make the background black and set the background of the CheckBox to TemplateBinding Background you will notice that a littlebit of the checkbox is getting black. This has to do with the build-in style of the CheckBox.
Just a guess, maybe Background was originally bounded to something in the default Template which you override.
Maybe you can try fixing that by adding a TemplateBinding for Background on the CheckBox:
<CheckBox x:Name="chkbxCheckAll" ... Background="{TemplateBinding Background}">
By the way, this is untested.

Resources