I am running Windows XP on my computer, and another computer also is running Windows XP.
In my WPF application, I've changed the styles of my buttons to appear as if they are not highlighting when rolled over, clicked, etc.
On my computer, this is the behavior that is occurring. On the other Windows XP system, I am seeing some outlining of the buttons with I roll over them or click.
Any ideas on why this is happening?
EDIT
Here is the Button itself
<Button Click="Next_Click" Width="100" VerticalAlignment="Center" BorderThickness="0" BorderBrush="Black" Background="Black" IsTabStop="False" DockPanel.Dock="Right" HorizontalAlignment="Left" Height="154" Name="NextOffers">
<Image Source="Images/offer_right_arrow.jpg" Width="100" Height="154" MaxWidth="100" MaxHeight="154" HorizontalAlignment="Left" VerticalAlignment="Top" MinWidth="100" MinHeight="154" ></Image>
</Button>
Also this Style, too.
<Style TargetType="{x:Type ListBoxItem}" x:Key="ListBoxItemStyle">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown"></EventSetter>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Padding="0,0,2,0" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Black"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I don't have a template made for this button, obviously.
I am loading my ResourceDictionaries dynamically in the code behind.
It sounds like you need a custom control template for your buttons. The default control template for most WPF controls is dependent upon the Windows theme that is selected, so that a button follows the theme whether you're on the Windows Classic theme, Aero, Royale, or whatever. If you want it to look exactly the same no matter what OS or theme the user has chosen, you'll save yourself a lot of headache using a custom control template.
Google "Show me the template" for an app that will give you the control template source (XAML) for each theme. This is a good starting point for creating custom templates.
The problem you're seeing is most likely due to the default Button Chrome. You can apply all sorts of styling, but if you leave that Chrome intact, the Windows theme is going to rear its ugly head.
You'll need to recreate the ControlTemplate itself.
Related
I've this code in C# to create a button as a child of a StackPanel:
`
Button myButton = new Button();
//All button stuff (Background, text...).
myStackPanel.Children.add(myButton);
`
But, as every button, it highlights every time the mouse is over or when I click it. Is there any way to change that in an easy code (I'm still new to C#) can remove that highlight.
I don't know how to do this. I haven't seen anything explaining this and the only codes I could find were in XAML, and I didn't understand them so couldn't translate them to C#.
The problem is all the code I find is about retemplating the XAML code. What I need is to do what I mentioned in C#, as the control is created from scratch in C#.
I took a look at a few of the answers for this and didn't see any I liked much.
WPF controls are lookless, meaning they have fixed behaviour but not specific look to them. You can re template a wpf control to pretty much anything you can describe in xaml. Many wpf controls have quite complicated templates.
Here's one way to template a button as described.
I've put this style in my window's resources. Usually such styles are in resource dictionaries which are merged in app.xaml.
<Window.Resources>
<Style x:Key="NoMouseOverButtonStyle" TargetType="{x:Type Button}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" >
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Style="{StaticResource NoMouseOverButtonStyle}"
Content="This is my Button"
Click="Button_Click"
HorizontalAlignment="Left"
VerticalAlignment="Top"
/>
</Grid>
</Window>
The button references the style as a resource.
That style sets some defaults so the button has a border you can see but over ride.
The contentpresenter is critical because this is where whatever you make content of your button will appear.
If I set an actual value on a button then that will over ride the style.
Hence
<Button Style="{StaticResource NoMouseOverButtonStyle}"
Content="This is my Button"
Click="Button_Click"
HorizontalAlignment="Left"
VerticalAlignment="Top"
BorderBrush="Red"
/>
Gives me a red border on my button.
A lightgray border is rather simpler than a button has by default.
You could reproduce that. Maybe that'd be an interesting learning exercise.
Lookup the button template on msdn.
Google: "wpf button template msdn"
Take a look at that. Brace yourself - it is complicated.
See the button border brush is hard coded in the template?
Change the style above so it does the same.
Clue:
<Setter.Value>
I'm quite new to WPF and MVVM and I'm trying to create a custom WindowChrome with all the standard Window features. I'm struggling with the Maximize/Minimize window Button content: I want the content to change when the user double clicks the WindowChrome bar, in order to show the right icon:
When I double click the bar, the result should be:
I managed to change the content with the Button Triggers, but how can I change it when another control event occurs?
Thanks in advance for the help!
Give the Button a Style with triggers that set the content based on the value of Window.WindowState. This isn't an event. The button reflects the current state of the window.
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger
Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}"
Value="Maximized">
<Setter Property="Content">
<Setter.Value>
<!-- I don't know if you're using a Path or what -->
<Path Stroke="White" Data="..." />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger
Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}"
Value="Normal">
<Setter Property="Content">
<Setter.Value>
<!-- I don't know if you're using a Path or what -->
<Path Stroke="White" Data="..." />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
It would be wiser to set the Template of the button instead, because there’s only one copy of each of those Paths, and if you reuse the style twice, they can’t be shared.
If there's some reason why this won't work with your code, show me your code.
I have come across an annoying issue in a WPF development (.net 3.5 sp1) I have been undertaking which involves showing some Tabs down the side (and rotated) on my interface.
I have been developing on a Windows 7 machine with the normal Aero theme and the tabs look fine
When we deployed to the customer, their machines are set on "Windows Classic" theme and the tabs show as
So they are all 'squashed' and don't display the text. If I switch my machine to Windows Classic then I am able to reproduce. I looked at the interface with WPF Inspector and could see some padding values that shouldn't be there
If I change the padding values to 0 using WPF Inspector, then the tabs start showing correctly again !! I have set the padding to be 0 on the template I have for this, but it doesn't seem to be having any affect
<TabControl TabStripPlacement="Left"
SelectedIndex="{Binding CurrentTabIndex}"
ItemsSource="{Binding CurrentPassengers}">
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Padding"
Value="0" />
<Setter Property="Margin"
Value="0" />
<Setter Property="Width"
Value="26.5" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<ContentPresenter Content="{Binding NameInGDSFormat}">
<ContentPresenter.LayoutTransform>
<RotateTransform Angle="-90" />
</ContentPresenter.LayoutTransform>
</ContentPresenter>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabControl.ContentTemplate>
<!-- Lots of stuff in here for the Content Template -->
</TabControl.ContentTemplate>
</TabControl>
I have tried setting various templates, padding on various elements but nothing seems to change - so does anyone know how I can fix this ?
EDIT: If I remove the 'width' that is set, then it does actually show in Windows Classic - but the tab is very WIDE.
OK - so in the end I had to create a whole new ControlTemplate to fix the issue :)
Basically I found the following within the original Classic ControlTemplate
<ContentPresenter RecognizesAccessKey="True"
Content="{TemplateBindingReaderedContentControl.Header}"
ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
ContentStringFormat="{TemplateBinding HeaderedContentControl.HeaderStringFormat}"
ContentSource="Header"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{TemplateBinding Control.Padding}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
So someone thought it a good idea to bind the Margin to the Padding and then when you place the Tabs on the left (or right) the template further added
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelected">
<Condition.Value>
<s:Boolean>True</s:Boolean>
</Condition.Value>
</Condition>
<Condition Property="TabItem.TabStripPlacement" Value="{x:Static Dock.Left}"/>
</MultiTrigger.Conditions>
<Setter Property="Control.Padding">
<Setter.Value>
<Thickness>11,2,14,2</Thickness>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Margin">
<Setter.Value>
<Thickness>-2,-2,-2,-2</Thickness>
</Setter.Value>
</Setter>
</MultiTrigger>
So they set the Padding to 11,2,14,2 (the values I was seeing in WPF Inspector).
So I had to override the Template, set the Margin to something sensible and then set the padding to more realistic values that could handle the content presenter being rotated 270 degrees :)
Hope this helps someone else who comes across this !!
I have PortItem which derived from ContentControl, TextedStackPanel derived from StackPanel which contains PortItems. And in MainWindow i have 2 StackPanels which contains TextedStackPanels . In PortItem i have overridden MouseLeftButtonDown method. But when i do this on this method isn't fired. I searched here in the forum, and found that Background property of Grid/StackPanel must be set to Transparent. I applied this, but there is no changes. What to do ?
EDIT 1
I use partial classes. I have 2 classes: PortItem.cs and PortItem.cs.xaml. I modifiy any visual changes in this XAML file.
EDIT 2
Also any mouse events aren't fired. Triggers which i use IsMouseOver are also dont work when i keep mouse on PortItem
XAML
<ContentControl x:Class="**.PortItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UI="clr-namespace:**.UIData" Width="17" Height="17" Margin="3" SnapsToDevicePixels="True" >
<Grid Background="Transparent" Name="mainGrid">
<!-- transparent extra space makes connector easier to hit -->
<Rectangle Fill="Transparent" Margin="-2"/>
<Border BorderBrush="Green" x:Name="border" BorderThickness="2">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}, Path=IsMouseOver}" Value="True">
<Setter Property="Border.BorderBrush" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Border.BorderBrush" Value="Blue"/>
</DataTrigger>
<!--<DataTrigger Binding="{Binding ContactPort}" Value="{x:Null}">
<Setter TargetName="border" Property="Border.BorderBrush" Value="Green"/>
</DataTrigger>-->
</Style.Triggers>
</Style>
</Border.Style>
<Image Source="/**;component/Resources/1337238611_port.png">
</Image>
</Border>
</Grid>
Make sure that you haven't set 'IsHitTestVisible' to false on your PortItem. Also, make sure no other controls are on top of it. If they are, set their 'IsHitTestVisible' property to false and then your PortItem control will get the mouse right click event. To make sure nothing is on top, declare your put your PortItem as the last thing added to your TextedStackPanel. To double check that nothing else is on top, change the background color of other controls to something really noticeable (just for testing) to see if anything is covering your PortItem control. Also, change the color on your PortItem control to verify that it is really where you think it is. Then once you get it all working, change the colors back to their original colors.
If you could give us a code sample of your XAML, that might help. If you're adding the PortItems dynamically in code behind, supply that code too.
Edit: in light of the changes you've made to your code, try to add ClipToBounds="False" to the top of your user control declaration.
<ContentControl x:Class="**.PortItem" ClipToBounds="False"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UI="clr-namespace:**.UIData" Width="17" Height="17" Margin="3" SnapsToDevicePixels="True" >
Have you created a template for your PortItem? I created the follow class to replicate your PortItem and break point on the base.OnMouseButtonDown line and it fires, I think the reason your method is not executing is because there is no visual element for the mouse to actually interact with, try adding the style below to your app and you should see the method fire properly.
public class PortItem: ContentControl
{
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
}
}
then in XAML I created a style to give it something to render.
<local:PortItem Margin="44,36,156,95">
<local:PortItem.Style>
<Style TargetType="{x:Type local:PortItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PortItem}">
<Border Background="Transparent">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:PortItem.Style>
</local:PortItem>
The background being Transparent that you mention you can see in the border control, if you leave the background out you are correct, the event never fires.
I have an Image control on my WPF Form. How can I create a border around it during runtime?
Here's my XAML code:
<Image Margin="2.5"
Grid.Column="1" Grid.Row="0"
x:Name="Behemoth" Source="Images/Hero/Behemoth.gif" Stretch="Fill"
MouseEnter="HeroMouseEnter"
MouseLeave="HeroMouseLeave"
MouseDown="HeroMouseClick" />
Also, I want to know how to remove the border.
Maybe if I state my problem better there is an even better solution available.
I have many Images, and when a user says: "Hey, just show me the woman out of all the picture." I want a way to sort of highlight or draw the users attention to whatever images I need them to see. I was thinking about adding a border, but maybe that's too much work for something that can be solved easier.
Any help?
Although it's visually very different from a border, you could use an outter glow to signify the importance of the image. Then, you don't have to change the parent of the image.
Alternatively, you could use a custom Adorner to place a border around the image. Good info on Adorners can be found on msdn.
There's no straightforward way to do it, because the Border is a container, so you would have to remove the Image from its parent, put the Border instead, and put the Image back in the Border...
Another option would be to use templates :
<Window.Resources>
<ControlTemplate x:Key="imageWithBorder" TargetType="{x:Type Image}">
<Border BorderBrush="Red" BorderThickness="2">
<Image Source="{TemplateBinding Source}" />
</Border>
</ControlTemplate>
</Window.Resources>
...
<Image Name="image1" Source="foo.png"/>
When you want to put the border around the image, just assign the template to the image :
image1.Template = this.FindResource("imageWithBorder") as ControlTemplate;
For your stated needs, I suggest you use a ListBox with a custom ItemContainerStyle - one that always has a border but only makes it visible if the item is selected.
Here's the basic idea:
<ListBox ItemsSource="{Binding MyImageObjects}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter ElementName="border" Property="BorderBrush" Value="Blue" />
<Setter ElementName="border" Property="BorderThickness" Value="2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>