This question already has answers here:
How to remove default mouse-over effect on WPF buttons?
(8 answers)
Closed 1 year ago.
I have a button in Visual Studio WPF and when I hover over it, you can see it gets lighter.
https://i.stack.imgur.com/l9kJh.png
How can I remove this? I tried looking up the solution but I'm a beginner so I don't understand how to implement given solutions.
You have to override the ControlTemplate. When you override it you have to re-implement the behavior (visual states) that is triggered by user interactions e.g., pressed, mouse over, disabled.
Only implement the triggers you need and leave the ones you want to avoid. In your case simply don't implement the mouse over visual state trigger:
App.xaml
<ControlTemplate x:Key="NoMouseOverButtonTemplate"
TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<!-- Add only required visual state triggers -->
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Background"
Value="{x:Static SystemColors.ControlLightBrush}" />
<Setter Property="Foreground"
Value="{x:Static SystemColors.GrayTextBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Usage
<Button Template="{StaticResource NoMouseOverButtonTemplate}" />
To know the required elements contained in the ControlTemplate that are mandatory for the templated control to perform as expected check the Microsoft Docs: Control Styles and Templates page (in your case the Button Styles and Templates page) and check for named parts as some controls require certain elements to carry a certain name in order to be identified.
You can also use the default template provided there as a starting point to design or customize controls.
Need to set it up so the Background color would be the same color for "IsMouseOver" Trigger as is for default.
Same as this solution just keeping the colors the same
Change color of Button when Mouse is over
<Button Width="50" Height="50" Content="Hi" Click="ButtonBase_OnClick" >
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Related
I'm writing an application where the user has to click "edit" in a few particular views to be able to edit them, I've solved this by binding the controllers (textboxes, comboboxes etc) IsEnabled to my "NotReadOnly" property in the VM.
Now my users want to be able to copy data from my controllers (in particular, the textboxes) without having to click my edit button first. This is not possible since IsEnabled=false disables most functionality.
Changing to "IsReadOnly = True" is not an alternative, I want the look and feel of a disabled controller (background, font changes etc) so that my users can clearly see it's not in edit mode, and I don't want to do all of that with bindings to my "ReadOnly" property in the VM, there are also cases where more than one background property determines wether some controller is enabled or not.
So I hope to find some way of getting copy (and preferably also selecting/scrolling) working in disabled controllers.
If that's not possible, is there any way of getting the look and feel of a disabled controller without having to add a ton of XAML to every single controller?
It is not possible to select text from disabled textbox. What you can do is make it read only and set the similar to disabled.
<TextBox IsEnabled="False">Disabled</TextBox>
<TextBox IsReadOnly="True" Text="Readonly" Background="LightGray" Foreground="Gray"></TextBox>
see this post: How to change disabled background color of TextBox in WPF
You do not to have to add XAML to each window where there are your controls. Just add this code to App.Xaml file of your WPF project and all your textbox controls in your application will have the same behavior for IsEnabled=false:
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="Red" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="White" />
<Style TargetType="TextBox">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" />
<Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" />
<Setter TargetName="PART_ContentHost" Property="Background" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you want your styles to be used all over the application, across different windows, you can define it for the entire application:
<Application x:Class="WpfApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
StartupUri="MainWindow.xaml">
<Application.Resources>
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="Red" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="White" />
<Style TargetType="TextBox">
<!--The code omitted for the brevity-->
</Setter>
</Style>
</Application.Resources>
</Application>
Read this superior tutorial about Styles
I'd like to have a Radio Button whose IsEnable property doesn't make any change in its visual appearance. However, the Radio Button shouldn't allow user to do anything when its IsEnable property is False.
I just want want to have a Radio Button which looks same irrespective of its IsEnable property. Apart from Visual appearance everything else should work as it is.
You may find it as a strangest requirement. But I want to achieve this. I'm using Radio Buttons as List Box items in List Box. Everything works good, but the problem occurs when user do Ctrl Mouse Left Click on checked Radio button. That's where everything fails.
Please help me.
You will have to extract the ControlTemplate of a RadioButton and then remove the style for Disable trigger. Below is an example of a standard template for a RadioButton. Just comment out the trigger IsEnable = False
<Style x:Key="RadioButtonStyle1" TargetType="{x:Type RadioButton}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="#F4F4F4"/>
<Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Themes:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{TemplateBinding IsChecked}" IsRound="true" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"/>
</BulletDecorator.Bullet>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
<Setter Property="Padding" Value="4,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Ashwin,
Its Very simple
Just follow the steps.
Right Click on the RadioButton, Edit Template and Edit a Copy
Then go to the Style created and comment out the code in storyboard of Disabled Visual state as shown in this image "http://i.stack.imgur.com/3TNoR.png"
Then it must look same for both states.
Take a look at the result "http://i.stack.imgur.com/fCL47.png"
Hope it solved your purpose.
Thanks,
I have a RichTextBox that has some content. I want to hide the scrollbar and remove the border when the user moves the mouse over it.
I have added FocusVisualStyle="{x:Null}" which I read in this link: Remove focus rectangle on a UserControl
See below:
<RichTextBox HorizontalAlignment="Left" Height="105" Margin="48,42,0,0" VerticalAlignment="Top" Width="614" Background="Transparent" IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Hidden" BorderBrush="Transparent" ScrollViewer.CanContentScroll="False" FocusVisualStyle="{x:Null}">
</FlowDocument>
blah blah
</FlowDocument>
</RichTextBox>
But wheneever the user moves the mouse over it I still see a white border appear and I can scroll up and down.
Why is this??
That's not FocusVisual you are seeing instead its MouseOver effect which is applied by default for RichTextBox.
You need to override default template to remove that effect which is applied via trigger (in case UIElement.IsMouseOver value is true).
Create a style and provide your own template ( In case you want it to be applied for all RichTextBoxes in your app put this in app resources or window resources wherever it fits in your code. Otherwise you can declare it inline just for your RichTextbox):
<Style TargetType="RichTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBoxBase">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="border"
SnapsToDevicePixels="True">
<ScrollViewer HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Name="PART_ContentHost"
Focusable="False" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="UIElement.Opacity" TargetName="border"
Value="0.56"/>
</Trigger>
<!--<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" TargetName="border">
<Setter.Value>
<SolidColorBrush>#FF7EB4EA</SolidColorBrush>
</Setter.Value>
</Setter>
</Trigger>-->
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="Border.BorderBrush" TargetName="border">
<Setter.Value>
<SolidColorBrush>#FF569DE5</SolidColorBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notice the trigger i have commented in the above default template.
I am trying to implement dragdrop functionality in Listbox(with in the listbox). For dragging i am using Thumb control (Mythumb is the class inherited from thumb)
so i have set the items panel to Canves and set the style for list box item to following
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="150" />
<Setter Property="Margin" Value="5,2" />
<Setter Property="Padding" Value="3" />
<Setter Property="dcc:OutputConfigurationPanel.Left" Value="{Binding Left}"></Setter>
<Setter Property="dcc:OutputConfigurationPanel.Top" Value="{Binding Top}"></Setter>
<Setter Property="IsSelected" Value="{Binding IsSelected}"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid DockPanel.Dock="Bottom" >
<Grid>
<Border BorderBrush="Black" Background="Black">
<ContentPresenter x:Name="ContentHost" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<MythumbTemplate="{StaticResource MoveThumbTemplate}" Cursor="Hand" />
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Setter Property="Background" Value="#FF233B00" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The drag drop is working fine but the thumb doesn’t allow the item to be selected. After checking i found that the mousedown event is not firing.
Is there a way to enable the select the items in usual ways?
A Thumb will always eat mouse clicks, same as button.
As I see it, you have two options:
From the code of the thumb, search up until you find the list box item and then set it's IsSelected property to true.
Scrap the thumb and create a Behavior that deals with dragging but doesn't handle mouse events (i.e. doesn't set e.Handled=true;) - this will preserve list box functionality.
Option 1 is probably faster, but I'd strongly consider to go with option 2 - less meddling with core controls functionality = better.
I have managed to get further with my read only check box after a bit of a break and now have the functionality I want in a reasonably elegant form. The problem is I have used a bit of a hack to make it work, although this is not a disaster it would be nice to do it better.
To recap: I want a regular looking checkbox that does not self check when it is clicked, instead the click event triggers a background worker that later on causes a variable to be updated. This variable is bound to checkbox.ischecked and it is then updated with the new value.
I would like to use a control template based on the idea here:
A read-only CheckBox in C# WPF
I have modified this and stripped out stuff I thought I didn't need (perhaps unwisely) and ended up with:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<!-- -->
<Style x:Key="ReadOnlyCheckBoxStyle" TargetType="{x:Type CheckBox}" >
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
<BulletDecorator.Bullet>
<Microsoft_Windows_Themes:BulletChrome Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
IsChecked="{TemplateBinding Tag}">
</Microsoft_Windows_Themes:BulletChrome>
</BulletDecorator.Bullet>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This checkbox works as described above and I call it like this:
<CheckBox x:Name="uiComboBox" Content="Does not set the backing property, but responds to it."
Style="{StaticResource ReadOnlyCheckBoxStyle}" Tag="{Binding MyBoolean}" Click="uiComboBox_Click"/>
The hack I made was to use the 'Tag' DependencyProperty to carry the data binding into the control template. This bypasses whatever mechanism is normally causing the checkbox to self check. To revert to a normal acting checkbox just change binding to Tag to a binding to IsChecked and inside the BulletDecorator set the TemplateBinding to IsChecked instead of Tag.
So I guess my questions are:
Have I got the wrong end of the stick? Is there a place where I can override whatever mechanism causes the box to self check? Perhaps in ControlTemplate Triggers?
Is it a good idea to go around eliminating any spare XAML that I think is just being brought in from the default CheckBox or should I try and keep a complete replacement for all styles?
If what I am doing is not too crazy, can I add a dependency property in XAML so that I don't have to use the Tag property?
It also occurs to me that perhaps what I really want is a button control that looks like a checkbox, maybe an invisible button with the usual animated checkbox on top which I bind data to the graphic of. Any thoughts on that plan would also be very welcome.
Thanks very much
Ed
I managed to sort out this problem and my ReadOnlyCheckBox idea, in the end I created a custom control based around Button and then applied a style to make it look like a CheckBox. I added my own IsChecked property that does not get set when the user clicks but is bound to the data so the displayed check only appears when the data changes.
C#:
public class ReadOnlyCheckBoxControl : System.Windows.Controls.Button
{
public static DependencyProperty IsCheckedProperty;
public ReadOnlyCheckBoxControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ReadOnlyCheckBoxControl), new FrameworkPropertyMetadata(typeof(ReadOnlyCheckBoxControl)));
}
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
static ReadOnlyCheckBoxControl()
{
IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(ReadOnlyCheckBoxControl));
}
}
XAML:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:ReadOnlyCheckBoxControlNS;assembly="
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />
<Style x:Key="EmptyCheckBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle SnapsToDevicePixels="true"
Margin="1"
Stroke="Black"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle SnapsToDevicePixels="true"
Margin="14,0,0,0"
Stroke="Black"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
<BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
<BulletDecorator.Bullet>
<Microsoft_Windows_Themes:BulletChrome Background="{StaticResource CheckBoxFillNormal}"
BorderBrush="{StaticResource CheckBoxStroke}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
IsChecked="{TemplateBinding IsChecked}">
</Microsoft_Windows_Themes:BulletChrome>
</BulletDecorator.Bullet>
<ContentPresenter SnapsToDevicePixels="True"
HorizontalAlignment="Left"
Margin="4,0,0,0"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}" />
<Setter Property="Padding" Value="4,0,0,0" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>