WPF Switch ToggleButton Content - wpf

I've defined the following xaml for a toggle button
<ToggleButton Style="{StaticResource AppMenuVisibilityToggleButtonDark}"
IsChecked="{Binding Path=IsVisible, UpdateSourceTrigger=PropertyChanged}"/>
with the style
<Style x:Key="AppMenuVisibilityToggleButtonDark" TargetType="{x:Type ToggleButton}">
<Setter Property="Content">
<Setter.Value>
<materialDesign:PackIcon Kind="HideOutline"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<materialDesign:PackIcon Kind="ShowOutline"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
However, when I have multiple use cases of this button, i.e., the xaml button is used in as part of an ItemTemplate in a ListBox, the content randomly just disappears only to reappear again when I click on the toggle button, but that then causes one of the other toggle button's content to disappear (see below where bottom item doesn't display any content for the "visibility" eye icon).
Given how my style is set up, I don't see how the content should ever just disappear. Am I missing something?

Related

Tabbing focus not working with control template that wraps control

I've tried all kinds of template binding and such to get this to work, but if I use this style on a control, the internal textbox control doesn't show focus.
I'm doing this because I want to set an error template that wraps around the textbox and the spot reserved for displaying units.
Now, typing in the box correct updates the text inside. And clicking on it will show the highlighted border and input caret, but tabbing into it won't.
<Style x:Key="Special" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<DockPanel
LastChildFill="True"
Visibility="Visible">
<Border
Name="PART_UnitContainer"
DockPanel.Dock="Right"
Visibility="Collapsed">
<Label
Content="ft"
Style="{DynamicResource UnitLabel}"
/>
</Border>
<TextBox Name="PART_Control" Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="PART_UnitContainer" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Initially I set the whole control as no tab stop, and internal one with tabstop, but apparently you also have to set the tab navigation to continue. I didn't when I tried playing with navigation, so I overlooked this setting.
<Style x:Key="Special" TargetType="{x:Type TextBox}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<ControlTemplate>
...
<Text IsTabStop="True" Name="PART_Control" ...
...
</ControlTemplate>
</Setter>
</Style>
However, this little trick doesn't work for shift-tab out of an editable combobox. I'll update the answer if I figure it out.
For comboboxes you have to do it differently. You don't set TabNavigation to Continue, and you don't set IsTabStop on internal combobox to true.
See
<Style x:Key="Special" TargetType="{x:Type ComboBox}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<ControlTemplate>
...
<ComboBox Name="PART_Control" ...
...
</ControlTemplate>
</Setter>
</Style>

Background color of button not showing up after using control template in WPF

Beginner question here.
I have a button whose Background is bound to a property in my
ViewModel. The same button also has a command whose implementation is
in my ViewModel. The clicking toggles a boolean in my VM & that
changes both the text & color of that button. All good so far, but
when my mouse hovers over, I get this blue color to remove which I
have a control template in my Style. Problem is now upon button click,
only text changes, no background change & no mouse over change. Following is my Button definition
<Button x:Name="OnlineBtn"
HorizontalAlignment="Left"
Margin="206,6,10,10"
Grid.Row="2" VerticalAlignment="Top" Width="50" Height="41"
Command="{Binding Path=OnlineCommand}"
Background="{Binding OnlineButtonProp,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Black"
Style="{StaticResource OnLineButtonStyle}">
And below is my Control Template definition.
<Style x:Key="OnLineButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
<ContentPresenter VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have seen the example on SO about how to set this control template, but my question is kinda two fold
1) Why is my IsMouseOver property not working
2) Why are my background color Button property that has bound props in my VM not working
The IsMouseOver Setter background is chosen RED just for testing the impact of the mouse over.
Setting a Background explicitly (as done with your Binding) has higher value precedence than the Setter in the Trigger. Hence the Trigger is ignored.
You should add an element like Border or Grid to your ControlTemplate where you set the Background with a TemplateBinding to the Button's Background. Then make the Trigger change that element's Background instead of the Button Background:
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" Background="{TemplateBinding Background}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Wrap panel not working for radio button with content template binding style?

I am new at WPF. I have list of radio button in menu of WPF application. I changed the style of radio button to look like textblock as submenu. Now problem is when I am trying to wrap and image and text inside radio button it's not showing it. but if i remove the style that I added on radio button to look and feel like textblock then wraping is just working fine but then it's display radion button Icon which I not needed.
Please refer to below code :
<StackPanel.Resources>
<Style x:Key="RadioButtonMenuStyle" TargetType="RadioButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<TextBlock Text="{TemplateBinding Content}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Height" Value="36"/>
<Setter Property="Foreground" Value="Black" />
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
------------------------------------------------------------------------
<RadioButton Name="rbttest" GroupName="rbtgroup" Background="{x:Null}" Style="
{StaticResource RadioButtonMenuStyle}" IsChecked="True">
<WrapPanel>
<Image Source="/WpfApplication1;component/Images/Test.ico" Width="16" Height="16"
Margin="0,0,5,0" />
<TextBlock Text="Test" Foreground="Green" />
</WrapPanel>
</RadioButton>
Is the templateBinding Content causing the problem ?
In your template, you are binding TextBlock.Text to RadioButton.Content, but your RadioButton content is actually a UI element (WrapPanel).
Get rid of the TextBlock in the template and replace it with a ContentPresenter. You don't need to set any properties on the presenter; it already knows how to locate the content on the templated parent.

WPF Menuitem Border

I've run into a problem trying to implement a Menu and can't figure out what is going on. I'm trying to make a single-layer menu using the Menu control. Here is my menu code:
<Menu DockPanel.Dock="Top" Height="22" Name="menu1" VerticalAlignment="Top" Background="#FF325170">
<MenuItem Header="Featured" Style="{StaticResource menuItemStyle}" />
<MenuItem Header="Search" Style="{StaticResource menuItemStyle}" />
</Menu>
And my style for my MenuItems is as follows:
<Style x:Key="menuItemStyle" TargetType="{x:Type MenuItem}">
<Style.Triggers>
<Trigger Property="MenuItem.IsMouseOver" Value="true">
<Setter Property = "Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
When I mouseover the menu items, there is a Border that appears, and I can't figure out for the life of me how to remove this border. Any suggestions?
For a lot of the built-in WPF control styles, you need to override the ControlTemplate.
Here is the MSDN page that provides the Menu ControlTemplate, with instructions on how to use it -- basically you are inserting local copies of all the styles for the Menu control, which then override the default control look and feel.
To address your problem you should be able to just insert this style:
<Style x:Key="{x:Type Menu}" TargetType="{x:Type Menu}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Menu}">
<!--Here is where you change the border thickness to zero on the menu-->
<Border BorderThickness="0">
<StackPanel ClipToBounds="True" Orientation="Horizontal"
IsItemsHost="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Wpf Datagrid Virtualization Issue when setting cell colors

I'm working with the wpf toolkit datagrid and have a column that is populated with toggle buttons. Using the below style I change the background color if the toggle button is selected and also on mouse over. Unfortunately if I have virtualization enable, when I make a select of a toggle button in a cell and scroll down in the grid I will find other cells that have also had their background changed. I assume this is a bug in how virtualization is reusing the cells as I scroll. Any suggestion to get around this and still use virtualization?
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock x:Name="Tb" Tag="{TemplateBinding Property=Tag}" Padding="{TemplateBinding Property=Padding}" Text="{TemplateBinding Property=Content}" >
</TextBlock>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Tb" Property="Background" Value="{StaticResource HoverRed}" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Tb" Property="Background" Value="{StaticResource SelectYellow}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've been able to get around the issue, by binding the IsChecked property of the togglebutton that the style is targeting. This allows me to have virtualization turned on and keeps the background color for the templated toggle button in each cell properly in sync with what it should be.
<ToggleButton Tag="button" IsChecked="{Binding Path=Selected,Mode=TwoWay}" FocusVisualStyle="{x:Null}" Content="{Binding Path=MarkerName,Mode=OneWay}">
</ToggleButton>

Resources