I have a WPF menu with a separator that I'd like to be black and 1 pixel wide. However, the separator seems to have a built-in 30 pixel wide buffer space that I can't change the color on. In the example below I set my separator to 50 pixels wide--as you can see the first 30 pixels don't reflect the proper background color. Very annoying! What am I missing?
Here's the XAML:
<Menu DockPanel.Dock="Top" FontSize="45" Height="62" Name="Menu">
<MenuItem Header="_Home" Name="HomeMenuItem" Click="HomeMenuItem_Click" Padding="10,0,10,0"></MenuItem>
<Separator Width="50" Background="Black" Foreground="Black" BorderThickness="0" Margin="0" Padding="0"></Separator>
<MenuItem Header="_Print" Name="PrintMenuItem" Click="PrintMenuItem_Click" Padding="10,0,10,0"></MenuItem>
...
Turns out the ControlTemplate for the menu automatically includes margin for the Separator. Thanks to Rowbear I now understand that the ControlTemplate overrides styles. The solution then was to add a custom template to the Application.Resources. (I'm sure it would have worked just fine to do it in Windows.Resources, etc.)
<Style x:Key="SeparatorStyle" TargetType="{x:Type Separator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Separator}">
<Border Padding="0" Margin="0" BorderThickness="0" Background="#40000000"></Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then in the main XAML window references the custom ControlTemplate like this:
<Separator Width="1" Style="{StaticResource SeparatorStyle}"></Separator>
Related
So, I have a grid, containing 3 columns. 2 one is gridsplitter which is working fine.
In the first one I have a ListView
<ListView Grid.Row="1"
ItemsSource="{Binding Chats}"
Background="Transparent"
BorderThickness="0"
ItemContainerStyle="{StaticResource ContactItem}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
Then there is Style: ContactItem
<Style TargetType="{x:Type ListViewItem}" x:Key="ContactItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<l:RippleEffectDecorator Background="Black" HighlightBackground="White">
<Border Height="62" Background="Transparent" BorderThickness="0">
</Border>
</l:RippleEffectDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see there is RippleEffectDecorator - which is ContentControl(I've found it in another case). There is link on github to it: Xaml file
And Cs file
So, starting the project I have:this
When I try to drag gridsplitter I have: this
I've already tried to put HorizontalAlignment and/or HorizontalContentAlignment Stretch to ListView/to ListViewItem style/to RippleEffectDecorator style.
Not problem about anything inside RippleEffectDecorator cuz when I was writing it without this contentcontrol it was working fine.
All I need is just everything inside this RippleEffectDecorator to be able to stretch horizontally when I'm moving gridsplitter, thank you!
I am trying to learn something about WPF and I am quite amazed by its flexibility.
However, I have hit a problem with Styles and DataTemplates, which is little bit confusing.
I have defined below test page to play around a bit with styles etc and found that the Styles defined in <Page.Resources> for Border and TextBlock are not applied in the DataTemplate, but Style for ProgressBar defined in exactly the same way is applied.
Source code (I just use Kaxaml and XamlPadX to view the result)
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="SkyBlue"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="CornerRadius" Value="5"/>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
<Style TargetType="{x:Type ProgressBar}">
<Setter Property="Height" Value="10"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
<XmlDataProvider x:Key="TestData" XPath="/TestData">
<x:XData>
<TestData xmlns="">
<TestElement>
<Name>Item 1</Name>
<Value>25</Value>
</TestElement>
<TestElement>
<Name>Item 2</Name>
<Value>50</Value>
</TestElement>
</TestData>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate DataType="TestElement">
<Border Height="45" Width="120" Margin="5,5">
<StackPanel Orientation="Vertical" Margin="5,5" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="{Binding XPath=Name}"/>
<ProgressBar Value="{Binding XPath=Value}"/>
</StackPanel>
</Border>
</HierarchicalDataTemplate>
</Page.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<Border Height="45" Width="120" Margin="5,5">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="Item 1"/>
<ProgressBar Value="25"/>
</StackPanel>
</Border>
<Border Height="45" Width="120" Margin="5,5">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="Item 2"/>
<ProgressBar Value="50"/>
</StackPanel>
</Border>
</StackPanel>
<ListBox Margin="10,10" Width="140" ItemsSource="{Binding Source={StaticResource TestData}, XPath=TestElement}"/>
</StackPanel>
</Page>
I suspect it has something to do with default styles etc, but more puzzling is why some Styles are applied and some not. I cannot find an easy explanation for above anywhere and thus would like to ask if someone would be kind enough to explain this behaviour in lamens' terms with possible links to technical description, i.e. to MSDN or so.
Thanks in advance for you support!
I discovered a simple workaround for this. For any elements that are not able to search outside the data template encapsulation boundary (i.e. are not being implicitly styled), you can just declare an empty style within the data template for that element type and use the BasedOn attribute of the style to find the correct implicit style outside the data template to apply.
In the example below, the TextBox is able to search outside the data template encapsulation boundary (because it inherits from Control?), but the TextBlock is not able to, so I declare the empty style for it which can search outside the data template.
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</DataTemplate.Resources>
<DockPanel>
<TextBlock Text="{Binding Name}" />
<TextBox Text="{Binding Value}" />
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
This is actually by design. Elements that do not derive from Control will not pick up implicit Styles, unless they are in the application resources.
This link explains this in more detail, or you can view the Connent bug report.
I've looked into this also, and I personally think it's a bug. I've noticed that the style is set if you name your styles like so:
<Style x:Key="BorderStyle" TargetType="{x:Type Border}">
etc...
and explicitly set your DataTemplate to use those styles:
<HierarchicalDataTemplate DataTemplate="TestElement">
<Border Height="45" Width="120" Margin="5,5", Style="{StaticResource BorderStyle}">
I think that it's possible that for DataTemplates (and maybe ControlTemplates), they default to having a null style, unless you explicitly set them.
That to me is not meant to happen - it's not a logical way of WPF working...
This is because ListBox is a logical parent of your datatemplate items, now remember, all properties those are "inheritable" like font, forecolor etc, are derived from the logical parent and ListBox already overrides it in its own default style, thats why this will not work. However in this case, you can use named styles as Mr. Dave has suggested, but I think if it does not work then this is a known problem in case of List Box etc, you can refere to my question here, i had similar problem in listbox, and the answers in my question are in more detail.
I was wondering if it is possible to insert my own bitmaps for scrollbar styling. I would like to to use an image for up/down arrows, background and scroller. This is what I have to start with, but I just don't know how to access these mentioned properties:
<TextBox Name="SlideNotes" Foreground="White" FontSize="20" FontWeight="Bold" Background="Transparent" BorderThickness="0" TextWrapping="Wrap" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Visible" Grid.Row="27" Grid.Column="11" Grid.ColumnSpan="46" Grid.RowSpan="5">
<TextBox.Resources>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="Red"/>
</Style>
</TextBox.Resources>
I would appreciate any help.
You can use ImageBrush to set an image to any property that uses Brushes (Background, Foreground, BorderBrush, Fill, etc.).
In your case, you'd use it like this:
<TextBox Name="SlideNotes" Foreground="White" FontSize="20" FontWeight="Bold" Background="Transparent" BorderThickness="0" TextWrapping="Wrap" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Visible" Grid.Row="27" Grid.Column="11" Grid.ColumnSpan="46" Grid.RowSpan="5">
<TextBox.Resources>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="yourimage.jpg" Stretch="Fill" />
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>
ImageBrush (and all other Brushes that inherit from TileBrush) has a set of properties that control how the image is shown. I've used Stretch="Fill" in my sample, which will make the image stretch to fill all the space available, but you could want it to behave differently.
For instance, this...
<ImageBrush ImageSource="yourimage.jpg" Stretch="None" TileMode="FlipXY" />
Will make your image repeat, with tiles alternatively flipped horizontally and/or vertically.
Toy around with Stretch and TileMode (or even ViewPort, ViewPortUnit, Viewbox and ViewboxUnit, if you feel brave enough) to get the effect you want.
EDIT - As with RepeatButton, the default ScrollBar template seems to pretty much ignore the Background property, most of the time, as well as other properties you could use for customization... This means you'll probably have to override the whole template to customize it to your liking.
Here's one ScrollBar template sample: ScrollBar Styles and Templates
And here's another for the RepeatButton: RepeatButton Styles and Templates
Looks like you're after a ControlTemplate. See here for a nice tutorial on how to style one.
To avoid having to style the entire ScrollViewer, you can instead style only the RepeatButton element, this will make things much easier to work with.
<Style TargetType="RepeatButton">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
You may need to define this style in the Window Resources, instead of the TextBox resources due to the scope.
See the documentation for RepeatButton styles and templates.
I have a custom tooltip style that basically creates a nice black tooltip with an arrow pointing to the location of the item you hovered over.
The problem is that sometimes the tooltip will not always be placed in the correct location (i.e. near window edges) which means the tooltip arrow no longer points at the correct place... Is there anyway around this problem? Or can I create specific styles for each location placement?
<Style x:Key="{x:Type ToolTip}" TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<StackPanel>
<Border CornerRadius="3" HorizontalAlignment="Center" VerticalAlignment="Top" Padding="10,7" BorderThickness="0" Background="#e5323232">
<StackPanel>
<TextBlock FontFamily="Arial" FontSize="12" Text="{TemplateBinding Content}" Foreground="#f0f0f0" />
</StackPanel>
</Border>
<Path Margin="10,0,0,0" Fill="#e5323232" Data="M 0 0 L 6 6 L 12 0 Z"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
Maybe you could try this, I just set the Placement to Center and added a HorizontalOffset to match the arrow you created in the template.
However that wont center it vertically on the control, so you could make an IValueConverter and calculate the size of the control and divide by 2, or you could add a dummy element to your StackPanel that is the same size as the Border, and that should center the ToolTip without needing any code behind
<Style TargetType="{x:Type ToolTip}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="Placement" Value="Center" />
<!--Offset to the arrow path-->
<Setter Property="HorizontalOffset" Value="15"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<StackPanel>
<Border x:Name="border" CornerRadius="3" HorizontalAlignment="Center" VerticalAlignment="Top" Padding="10,7" BorderThickness="0" Background="#e5323232">
<StackPanel>
<TextBlock FontFamily="Arial" FontSize="12" Text="{TemplateBinding Content}" Foreground="#f0f0f0" />
</StackPanel>
</Border>
<Path Margin="10,0,0,0" Fill="#e5323232" Data="M 0 0 L 6 6 L 12 0 Z"/>
<!--Dummy rectangle same height as tool tip, so it centers on the control-->
<Rectangle Height="{Binding ActualHeight, ElementName=border}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The simplest way of doing it is to use a UIElement that exists in the Control Tree as the PlacementTarget of the Tooltip. This will avoid the Silverlight automated positioning when you get near the window edges:
<StackPanel ToolTipService.ToolTip="{Binding Title, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
ToolTipService.Placement="Bottom"
ToolTipService.PlacementTarget="{Binding ElementName=LayoutRoot}">
<TextBlock Text="{Binding Title,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
In this case the tooltip will be positioned always at the Origin of the LayoutRoot element. If you have a fixed path size and the PlacementTarget is always at the same position relative to the control for which you want to show the tooltip then this works fine.
If you need to position the Tooltip relatively to the control that triggers the Tooltip than you have to make the Path Data dynamic and calculate the distance to create a new Path Data in the Tooltip control every time the Tooltip is opened.
For this case you have to handle the Tooltip.IsOpened event and implement this logic. If you're using the PlacementTarget than you always know the direction relatively to your control so this makes it easier to calculate the Path vertices.
Another way which works but it's way more complex is to implement your own Popup that shows up when you move the mouse over your control. You would need to implement a few calculations to get the position of the popup relative to the Control, which is exactly what the Tooltip control does for you. The advantage of this is that you have complete control over the positioning of the tooltip and its appearance.
I would like to create a style or template for rectangles. The properties are quite superficial: changed background color, radius.
In addition I would like to add text inside of the rectangle.
I've found alot of examples, but none fit my needs the best. Is it possible to create a template drawing the rectangle and text inside in a way I only need to call
<Rectangle template={StaticRessources myBox}/>
And the defined template is applied? So far I came, the text is not aligned inside the rectangle:
<ControlTemplate x:Key="greenBoxTemplate">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="25" Text="Hello World" TextWrapping="Wrap"/>
<Rectangle Height="100" HorizontalAlignment="Left" Margin="233,144,0,0" Name="BNU2" Style="{StaticResource greenBox}" Stroke="Black" VerticalAlignment="Top" Width="200"/>
</Grid>
</ControlTemplate>
For what it's worth, the template is applied to a button, but actually I want to apply it to rectangle which does not work.
What you need is a Decorator. There is one already that seems like to fit for you perfectly: Border
if you want to have a recurring border for elements with some predefined values you can create as Style like:
<Style TargetType="Border" x:Key="MyBorderStyle">
<Setter Property="Background" Value="Red"/>
<Setter Property="CornerRadius" Value="3px"/>
</Style>
and apply it like:
<Border Style="{StaticResource MyBorderStyle}">
<TextBlock>Hello World</TextBlock>
</Border>