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>
Related
I'm getting close to the understanding of the positioning of the System.Windows.Controls.UserControl objects:
By default, they don't have X or Y coordinates, relative to their container, but there is the possibility to add some, using so-called "Attached Properties".
A typical example of such attached properties are Canvas.Left and Canvas.Top, which mean that, in case the container of the UserControl is a Canvas, then the following happens with (supposingly) its upper left point (pseudo-code):
UserControl_UpperLeft_Point.X = Canvas.Left
UserControl_UpperLeft_Point.Y = Canvas.Top
Now what I'd like to know:
Is my idea correct? Is it indeed the upper left corner which is used?
What if I want to modify this behaviour, let's say into:
int left_Margin = 100;
int top_Margin = 200;
UserControl_UpperLeft_Point.X = Canvas.Left / 2 + left_Margin;
UserControl_UpperLeft_Point.Y = Canvas.Top * 2 + top_Margin;
What if I want to position my UserControl, based on the upper right corner or even the center?
Is my idea correct? Is it indeed the upper left corner which is used?
It is effectively the upper left corner in this case, but actually each of the sides are aligned. Furthermore, the control is aligned by the Canvas, it does not have internal X or Y coordinates that are set. They are given by the attached properties which are sepcific to the Canvas, no other panel. The Canvas internally calculates a rectangle where it draws the UserControl.
Canvas.Left
Gets or sets a value that represents the distance between the left side of an element and the left side of its parent Canvas.
Canvas.Top
Gets or sets a value that represents the distance between the top of an element and the top of its parent Canvas.
It is also important to note, that there is a priority for the attached properties.
If you specify them, the attached properties Canvas.Top or Canvas.Left take priority over Canvas.Bottom or Canvas.Right.
What if I want to modify this behaviour, let's say into: [...]
You would still have to assign the attached properties, but calculate the expression before.
Use a Binding or MultiBinding with a custom value converter that evaluates an expression that is bound or passed as converter parameter or with a specialized value converter to calculate a specific term.
Create your own specialized attached properties that internally assign the calculated value to the Canvas attached properties.
What if I want to position my UserControl, based on the upper right corner
Set the Canvas.Top and Canvas.Right attached properties instead.
<Canvas>
<local:MyUserControl Canvas.Top="0" Canvas.Right="0" Width="50" Height="80"/>
</Canvas>
[...] or even the center?
A Canvas is used for absolute positioning. If you want to center controls, a Grid might be the better choice. If you still want to use a Canvas and it is fixed size, just calculate the center coordinates yourself and set the attached properties accordingly. If it is resizeable and the position of the UserControl position needs to be responsive to that, you could do one of these.
Put a Grid around the Canvas and put the UserControl after it. It will appear on top of the Canvas and will be centered automatically, even on resizing.
Grid>
<Canvas>
<Rectangle Canvas.Top="80" Canvas.Left="20" Fill="Black" Width="50" Height="50"/>
<Rectangle Canvas.Top="300" Canvas.Left="230" Fill="Black" Width="100" Height="80"/>
</Canvas>
<local:MyUserControl Width="50" Height="80"/>
</Grid>
Implement a custom behavior or complicated bindings with converter using the bound ActualSize of the Canvas to set the attached properties, which I do not recommend.
I think for your last question it is more useful to ask why you need this behavior, what you want to achieve. Often there is a much simpler and more suitable solution.
If you want to position a control inside a container you should follow the WPF way.
Align it horizontal and vertical and set the margin, thats it.
<Grid>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="Background" Value="Red" />
<Setter Property="TextElement.Foreground" Value="White" />
<Setter Property="TextElement.FontWeight" Value="Bold" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="TextAlignment" Value="Center" />
</Style>
</Grid.Resources>
<!--#region top-->
<Border
Margin="20,20,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,20,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,20,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<TextBlock>
Top<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region center-->
<Border
Margin="20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Left</TextBlock>
</Border>
<Border
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="0,0,20,0"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock>
Center<LineBreak />
Right</TextBlock>
</Border>
<!--#endregion-->
<!--#region bottom-->
<Border
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Right</TextBlock>
</Border>
<Border
Margin="0,0,0,20"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Center</TextBlock>
</Border>
<Border
Margin="20,0,0,20"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<TextBlock>
Bottom<LineBreak />
Left</TextBlock>
</Border>
<!--#endregion-->
</Grid>
If you want to have the old style (knwon from WinForms you can align it HorizontalAlignemnt="Top" and VerticalAlignment="Left" and use the Left and Top property of Margin to set the old school Left and Top.
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>
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 would like to create an WPF Button with no border, with background image and insert a center Text. So I have this:
<Style TargetType="Button" x:Key="TransparentButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Style="{StaticResource TransparentButton}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="./Resources/Images/bottone_indietro.png" />
<Label content="Pippo"/>
</StackPanel>
</Button.Content>
</Button>
It works but Text "Pippo" is displayed at right of image. It possible to center the text???
Reguards...
If you want to centre align text over your image you could put both elements in a Grid instead of StackPanel
<Grid>
<Image Source="./Resources/Images/bottone_indietro.png" />
<Label Content="Pippo" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
StakcPanel will stack its children horizontally or vertically whilst Grid lets you put one element over other. From MSDN:
Child elements of a Grid are drawn in the order in which they appear in markup or code. As a consequence, layered order (also known as z-order) can be achieved when elements share the same coordinates
You can read more about WPF panels here
You can use the HorizontalAlignment property to centre your text, although it will always be to the right of your Image. You also would need to remove the Orientation setting on the StackPanel so that the text will appear underneath the Image... try this:
<Button Style="{StaticResource TransparentButton}">
<Button.Content>
<StackPanel>
<Image Source="./Resources/Images/bottone_indietro.png" />
<TextBlock Text="Pippo" HorizontalAlignment="Center" />
</StackPanel>
</Button.Content>
</Button>
Note that if you want your text to appear over the top of your Image, then you shouldn't use a StackPanel at all... in that case, you should replace it with a Grid instead.
What is this rectangle and how to get rid of it?
I am only templating scrollbars:
<Style TargetType="ScrollBar">
<Setter Property="Background" Value="#FF07468B"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid x:Name="GridRoot" Width="5" Background="{TemplateBinding Background}">
<Track x:Name="PART_Track" Grid.Row="0" IsDirectionReversed="true" Focusable="false">
<Track.Thumb>
<!-- thumb is defined somewhere -->
<Thumb x:Name="Thumb" Style="{StaticResource ScrollBarThumb}"/>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageDownCommand" Opacity="0" Focusable="false"/>
</Track.IncreaseRepeatButton>
<Track.DecreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageUpCommand" Opacity="0" Focusable="false"/>
</Track.DecreaseRepeatButton>
</Track>
</Grid>
<!-- removed triggers -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I doubt if it's a ScrollBar, more like ListBox itself. The problem only appears when horizontal scrollbar is visible.
To example, here guy templating ScrollViewer and as you can see image is without artefact or intersection (or resizegrip, or whatever).
Do I need to do something to ListBox when only templating scrollbars? And what exactly it will be?
Making ListBox background Red will produce following:
So this rectangle is something LightGray, but from where it comes from?
The style of a "normal" scrollBar in a listBox or in a window is generic.
You cannot change the style as you want! This is a small detail that probably nobody thought about it.
Why do you see that rectangle?
Well, I guess the guys from Microsoft had this three possibilities:
1. Horizontal bar fills the intersection.
2. Vertical bar fills the intersection
3. Or there is a solid rectangle which has the same color as the proper scrollBar.
So, they decided to use the 3rd option. And also as I said, without changing the whole style of a scrollBar you cannot change that small detail. Maybe you can change with this style : http://www.nullskull.com/a/1525/styling-the-wpf-scrollviewer.aspx ?:D