Stop button color change on Mouseover - wpf

ok..this is very strange....i have defined a button, actually 5 buttons and each have a different color but on mouse over, they just change the color to that icy blue color....i tried to override that by using the below code :
<Button Name="btn1" Content="Button" Width="65" Height="45" Background="Green" Margin="1,1,0,1" FontWeight="Bold">
<Button.Style>
<Style>
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter Property="Button.Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.LayoutTransform>
<RotateTransform Angle="270"/>
</Button.LayoutTransform>
</Button>
but it still does not work...what i want is that it should maintain the background color it has been given(different for each button), so the question is : do i have to define it again and again for each button (the trigger did not work, color becomes ice blue) OR can i define it in the resource file with a generic value that it either stops the color change or just sets background to existing property
EDIT : Just to be clear, i want the button to stop changing its color on mouseover and just retain whatever color i have assigned it.....

Based on the comments and the SO post I linked: that article applied the style to anything of type Button, that's why it applies to all buttons (which is not necessarily a bad thing). But the salient point to take away from that article is that what you need to modify is the ControlTemplate.
So you would want to do something like this:
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Chrome" BorderBrush="Black" BorderThickness="2" CornerRadius="2" Background="{TemplateBinding Property=Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
This isn't perfect, because it loses all of it's interactivity (ie. you can't tell you've pushed it, hovered over it or anything). But it gives you a good starting point.
One of the key points here is that the Background property of the Border is bound to the TemplateParent Property=Background, that means it's going to read the background property of the button the that it is templating and use it's background color. This makes it easier for you to use a single style to cover all 5 of your buttons. You could (and may want to) do similar things with the BorderBrush property.
Also notice my style has a x:Key value, so in order to use this, you would do:
<Button x:Name="btn1" Content="Button" Width="65" Height="45" Background="Green" Margin="1,1,0,1" FontWeight="Bold" Style="{DynamicResource ButtonStyle1}">
<Button.LayoutTransform>
<RotateTransform Angle="270"/>
</Button.LayoutTransform>
</Button>
You can remove the x:Key attribute and the style will indeed apply to all buttons inside of whichever container you declare the resource.

Related

WPF variable custom button shape

I'm trying to desinge a Template for a Button, which addapts the shape of the Button. I want to give the shape as Attribute to the control. Like this:
<Button Style="{StaticResource MyStyle}">
<Button.Shape>
<ImageBrush ImageSource="MyImage"/>
</Button.Shape>
</Button>
I tried to use the OpacityMask-Attribute of the Button, but somehow I coulden't specify in the template on which element I want to apply the mask.
<ControlTemplate x:Key="Test" TargetType="Button">
<Grid Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<Rectangle Fill="{TemplateBinding Foreground}" OpacityMask"{TemplateBinding OpacityMask}">
</Rectangle>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#aaff00ff"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I already tried something like this:
<Button Style="{StaticResource MyStyle}">
<Button.OpacityMask>
<ImageBrush ImageSource="MyImage"/>
</Button.OpacityMask>
</Button>
But then i can't change the background anymore. I know, I could put every button in a Grid with the background I want, but I try to learn the concept of Templates and I wonder if there is a more elegant solution. :)

Round the corners of a button in Window.Resources WPF

I am very new to WPF. I've familiarized myself with ControlTemplate, ContentPresenter, and some other pieces, but I am struggling to create a button with rounded corners as defined from Window.Resources (or potentially a separate style file).
Anyways, when I add this to a <Button/> tag, I get a button with rounded corners:
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
</Style>
</Button.Resources>
However, when I try to include it up in the Window.Resources the button will not apply the border style:
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}"/>
<Border CornerRadius="5"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
This doesn't look right to me, but I guess I don't know where to add the specification of CornerRadius such that it will apply to the button. I did see this post, How to create/make rounded corner buttons in WPF? but it's a little over my head. I just want to round all the buttons in my application!
The Border in your ControlTemplate is not visible, because you have neither set its Background, nor its BorderBrush.
You could have something like shown below. Note however that with a simple ControlTemplate like this a Button loses all the visualizations of its states, like focused, mouse-over, pressed etc.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="5">
<ContentPresenter/>
</Border>
</ControlTemplate>
You may instead just declare a default Button Style (i.e. a Style resource without x:Key) that applies your original Border Style like this:
<Style TargetType="Button">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
</Style>
</Style.Resources>
</Style>

ContentControl in ControlTemplate does not show Border nor Background

I have a Button with a custom control template and a Grid as sibling. The Button should use the TriangleUpPath when the Grid is visible, otherwise it should use the TriangleDownPath. So far so good.
But I want that the Path has a Border around. So I thought I could just set the BorderBrush of the ContentControl, but this does not work. I don't see the Border. Same goes for the Background of the ContentControl.
Here is my minimal not working example:
<Button x:Name="_hideButton"
Grid.Row="0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Click="ToggleResultsVisibility">
<Button.Style>
<Style TargetType="Button" >
<Style.Resources>
<Path x:Key="TriangleUpPath"
Data="M 0,5 L 7,0 L 14,5"
Margin="3,3,0,0"
Stroke="Black"
StrokeThickness="1"/>
<Path x:Key="TriangleDownPath"
Data="M 0,0 L 7,5 L 14,0"
Margin="3,3,0,0"
Stroke="Black"
StrokeThickness="1"/>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentControl Margin="0,5,5,0"
Width="20"
Height="11"
BorderBrush="Magenta"
BorderThickness="1"
Background="Cyan">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Background"
Value="HotPink"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Visibility, ElementName=_resultsGrid}"
Value="Collapsed">
<Setter Property="Content"
Value="{StaticResource TriangleDownPath}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Visibility, ElementName=_resultsGrid}"
Value="Visible">
<Setter Property="Content"
Value="{StaticResource TriangleUpPath}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Grid x:Name="_resultsGrid"/>
As you can see, I even tried to set the Background in the Style (to HotPink) to no avail.
It helps, when I have a Border around the ContentControl.
But the question is: why do the Background-Property and the BorderBrush-Property of the ContentControl have no influence?
The default style for ContentControl does not contain a way of rendering the Border and Background properties, it just has a ContentPresenter.
You need to add a custom template for the content control yourself, containing the additional elements you need:
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" >
<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Cursor="{TemplateBinding Cursor}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</ContentControl.Template>
It's because BorderThickness/Brush aren't some magic properties that make the border magically appear out of nowhere.
For making borders, you should be using a <Border> element somewhere.
By default, the Button has some Border inside. That's why setting BorderBrush/BorderThickness on a Button does something. Specifically, the default control template of a Button contains a Border as one of its topmost elements, and that Border's definition looks similar to:
// the DEFAULT Button's control template
<ControlTemplate>
...
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
.... >
...here goes other things like textblock/content..
</Border>
...
</ControlTemplate>
so, as you see, there's a border and it has its settings bound to the owning control, so bound to the Button. The TemplateBinding binds BBrush of Border to BBrush of the Button that owns it.
Now, as you have completely rewritten/overridden the Button's control template, it now does not contain any Border, so there is nothing that would draw the border.
Try:
<Border BorderBrush=... BorderThickness=...>
<ContentControl ....
and it should be like you wanted.
Afterthought: If I understood you wrong and if you meant your setting the BorderBrush/Thickness on the ContentControl inside the buttons' template that it didn't add border around your paths, then there's a surprise.
The properties are available on the CC only because they are commonly used, they came from base Control class. But the ContentControl does not use them at all. They are ignored. ContentControl does not draw any borders, texts, etc. ContentControl shows its content, and the content is just a Path which draws itself only. So, either add a Border around the ContentControl as above, or change your resources and wrap each Path into a Border and use that as a content resource.
<Style.Resources>
<Border x:Key="TriangleUpPath"
BorderBrush=... BorderThickness=...
<Path Data="M 0,5 L 7,0 L 14,5"
.... />
</Border>
<Border x:Key="TriangleDownPath"
BorderBrush=... BorderThickness=...
<Path Data="M 0,0 L 7,5 L 14,0"
.... />
</Border>
</Style.Resources>

Make ErrorTemplate in Style on ComboBox allow tooltip but not mouse click

I use telerik, but that should not mean much for this question. My application is WPF (.Net 4.5).
I have a style, that I use for all comboboxes, which has an errortemplate. The style looks like this:
<Style TargetType="{x:Type telerik:RadComboBox}" x:Key="RadComboBoxStyle" >
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Background" Value="{StaticResource InputBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource InputBorderBrush}" />
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource RadComboBoxValidationErrorTemplate}" />
</Style>
My ErrorTemplate looks like this:
<ControlTemplate TargetType="{x:Type Control}" x:Key="RadComboBoxValidationErrorTemplate">
<Grid ToolTipService.IsEnabled="True" ToolTipService.ShowOnDisabled="True"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors), Converter={StaticResource ValidationErrorsConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border BorderBrush="{StaticResource ErrorBrush}" BorderThickness="3" Panel.ZIndex="999" HorizontalAlignment="Right" Margin="0,0,10,0"
Background="Transparent" DockPanel.Dock="right" Width="16" Height="16" CornerRadius="10">
<Rectangle Fill="{StaticResource ErrorBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="3" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="315" />
</Rectangle.RenderTransform>
</Rectangle>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="{StaticResource ErrorBrush}" BorderThickness="1" />
</AdornedElementPlaceholder>
</Grid>
</ControlTemplate>
The entire thing is defined in a global ResourceDictionary.
What this code does, it to put a "forbidden sign" on top of the combobox (Panel.ZIndex="999"), just before the dropdown button (using margins). The Border and the Rectangle makes a sign much like this: Picture.
The combobox itself must be able to hold a tooltip, set locally. So the error-message cannot be shown in the tooltip of the combobox - unless I find a way to combine the two without having to resolve it locally (I want that code in my resourcedictionary).
I also do not want the "forbidden sign" to handle mouse clicks (it gobbles up the click and prevent the combobox from dropping down, if the user clicks on the "forbidden sign".
I tried setting IsHitTestVisible to false on the grid and on the border inside the ErrorTemplate, but that caused the Tooltip to never show.
I also tried setting IsEnabled to false on the same two constrols, but that would not send the mouseclick on to the combobox itself (the list in the combobox does not drop down).
Is there any way to do this directly in the combobox-style or errortemplate? I do not even mind having a code behind - but I really do not want to add code locally where the combobox-style is used.

How to make a simple hyperlink in XAML?

All I want to do is make a little hyperlink in XAML. I've tried everything. I give up.
What is the syntax for this?
<StackPanel Width="70" HorizontalAlignment="Center">
<Hyperlink Click="buttonClose_Click" Cursor="Hand"
Foreground="#555" Width="31" Margin="0 0 0 15"
HorizontalAlignment="Right">Close</Hyperlink>
<Button Width="60" Margin="0 0 0 3">Test 1</Button>
<Button Width="60" Margin="0 0 0 3">Test 2</Button>
<Button Width="60" Margin="0 0 0 3">Test 3</Button>
<Button Width="60" Margin="0 0 0 3">Test 4</Button>
</StackPanel>
Visual Studio Team: In Visual Studio 2010 I want Clippy to pop up and say "It seems you are trying to make a hyperlink" and tell me how to do it. Can't you do that with MEF? It would be retro cool, and these little "how do I do what I already know how to do in HTML" issues burn up so much time during the learning process with XAML.
You can't add a Hyperlink to a StackPanel -- you'll get a runtime error. (Actually, I'm kinda surprised it's not a compile-time error.) That's because Hyperlink doesn't live in the "controls" side of WPF with <Button> and <StackPanel> and other things that are laid out on rectangular chunks of screen and descend from UIElement. Instead, it lives in the "text" side of things, with <Bold> and <Run> and <Paragraph> and other generally texty things that word-wrap and flow in lines and paragraphs and descend from TextElement.
Once you realize that there are two separate class hierarchies with different layout behaviors, it makes sense that Hyperlink would be on the "text" side of things (makes it easy to e.g. have a paragraph with a hyperlink in the middle, and even for that hyperlink to wrap across a line break).
But no, it's not so discoverable when you're starting out.
To mix the two worlds, and use a hyperlink as a control, all you need to do is put it in a TextBlock. TextBlock is a control-ish thing (i.e., can go in a StackPanel) that contains text-ish things (i.e., can contain a Hyperlink):
<TextBlock><Hyperlink Click="buttonClose_Click">Close</Hyperlink></TextBlock>
You can use a Button with a custom control template, the code below is a limited hyperlink style button (for example it only support textual hyperlinks) but maybe it'll point you in the right direction.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="Link" TargetType="Button">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock TextDecorations="Underline"
Text="{TemplateBinding Content}"
Background="{TemplateBinding Background}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Button Content="Click Me!" Style="{StaticResource Link}"/>
</Page>
Try this:
<TextBlock>
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
NavigateUri="http://www.msn.com">MSN</Hyperlink>
</TextBlock>
private void Hyperlink_RequestNavigate(object sender,
System.Windows.Navigation.RequestNavigateEventArgs e)
{
System.Diagnostics.Process.Start(e.Uri.AbsoluteUri);
}
<TextBlock>
<Hyperlink NavigateUri="{Binding YourUri}" RequestNavigate="YourRequestNavigate">
<TextBlock Text="{Binding YourText}" />
</Hyperlink>
</TextBlock>
This will linkify any binded text in the nested textblock, i have not found a better way yet, i would like the first textblock to not be there if possible.
This will work for DataTemplates aswell.
You may find that if you're binding to anything other than simple text values you will need to use ContentPresenter otherwise nothing will appear, this could be true if you're binding to an XML data source.
A Property Trigger for IsMouseOver gives the text an underline.
An example where I"m binding to XML is presented below.
<Style x:Key="JobNumberStyleButton" TargetType="{x:Type Button}">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock>
<ContentPresenter
Margin="0,0,0,0"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Padding="0,0,0,0" Margin="0,0,0,0">
<Underline>
<ContentPresenter
Margin="0,0,0,0"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Underline>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
You can simply use HyperlinkButton.
When it is clicked on, the URL will be displayed in your web browser:
<HyperlinkButton
NavigateUri="https://dev.windowsphone.com"
TargetName="_blank"
Content="Windows Phone Dev Center" />
Usually, the meaning of an Hyperlink is to give an anchor to send the user to another Page or generally speaking to another resource, so it's implemented in such a way and you have to specify the location for that resource like this:
<HyperLink NavigateUri="http://www.site.com">
Web Site
</HyperLink>
However, i've found this blog post with a custom TextBlock that is used as an HyperLink and supports click events.
in UWP with mvvmcross i'm using this
<HyperlinkButton Content="{Binding TextSource, ConverterParameter=MyUrl, Converter={StaticResource Language},
FallbackValue=_MyUrl}" NavigateUri="http://www.google.com" />

Resources