Annoying 1-pixel band between Border and Label? - wpf

I am trying to get rid of an annoying 1-pxel band of un-drawn background between a border and a label control.
Specifically, my XAML looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox Margin="0,0,5,3" HorizontalAlignment="Right" Grid.Column="1">
<Border BorderThickness="2" CornerRadius="2" BorderBrush="#BF272727" Background="#BF272727">
<Label Padding="-3" Content="Testing" Foreground="Red"/>
</Border>
</Viewbox>
</Grid>
And my output looks like this:
Notice that the border brush and the label background both have a semi-transparent color. I've fiddled with other properties of both the border and the label and haven't found anything that will cause this single pixel between the border and label to get filled with the background color. I imagine it is something simple, but I haven't stumbled on it yet. I've tried setting the Background property on the label instead of the border, but with no change in results.

WPF's device-agnostic rendering works very well most of the time, but yes…occasionally you'll see artifacts like this, due to adjacent elements being anti-aliased, causing pixels that nominally should be exactly the same color having some variation.
In your case, you should omit the border thickness and brush altogether. To do that and still have the same visual appearance, you need to include padding, so that the border element is expanded out to the size it would have had, had there been a non-zero thickness border. And of course, without the border included, the corner radius needs to be adjusted up (by half the original border thickness).
The following produces the result you seem to want:
<Border Background="#BF272727" CornerRadius="3" Padding="2">
<Label Padding="-3" Content="Testing" Foreground="Red"/>
</Border>

Turn on aliased edges in either your Border control or any of its parents:
RenderOptions.EdgeMode="Aliased"

Related

Why is this WPF border is showing around the column and not the StackPanel?

I'm trying to place a Border around a StackPanel like so:
<Border CornerRadius="5" BorderBrush="#009999" Background="Transparent"
BorderThickness="2" Grid.Column="2" Grid.Row="0">
<StackPanel HorizontalAlignment="Center" Margin="0,30,0,0">
<!--Contents-->
</StackPanel>
</Border>
For some reason, the border is appearing around the column that the StackPanel is in, not the StackPanel itself. I can change the margin of the border, but that doesn't hold up if the screen is resized. I also tried getting rid of the StackPanel margin but that made no difference. The StackPanel is the only object in this column.
Border has default HorizontalAlignment equal to Stretch, so it takes full possible width.
Then StackPanel is centered inside the border because it has HorizontalAlignment="Center".
set HorizontalAlignment="Center" on Border. It will get width, equal to StackPanel width (plus Margin), and then will be centered
I think it is because you're setting the HorizontalAlignment to Center. Doing this will make the StackPanel size to whatever its content is.
If you move the Border to stackpanel your problems will be fixed :)
here it is:
<Grid>
<StackPanel Width="350" Height="200">
<Border BorderThickness="2" BorderBrush="Black" Width="350" Height="200">
<TextBlock>SomeText</TextBlock>
</Border>
</StackPanel>
</Grid>

XAML- How to fix the position of an image relative to the right hand side of the display window?

I am developing an application for which the GUI is being written/ displayed using XAML. I have most of the desired elements displayed on the GUI at the moment, and am now working on the layout- positioning the various elements in particular places.
Most of the controls/ buttons, etc are aligned to the left, and stay 'bound' to the left hand side of the GUI even if I resize the window by dragging its left hand edge further to the left (the icons, etc move to stay their relative distance from the edge of the window).
However, I have one element which I want to align to the right, so that it will stay 'bound' to the right hand side of the GUI- if I resize the window by dragging its right hand edge further to the right, it should move to stay its relative distance from the edge of the window... at the moment, that element is staying at the position that I have drawn it (i.e. 900 pixels from the left), no matter what the size of the window is- so if I resize the width of the window to less than 900 pixels, that element cannot be seen.
The XAML markup I have used for the elements that I want bound to the left hand side of the GUI is, for example:
<Button Style="{DynamicResource NoChromeButton}" Click="backBtn_Click" Margin="0, 0, 0, 0" HorizontalAlignment="Left" >
<Image Source="C:\...\abc.png" Height="30" Width="40" />
</Button>
The XAML markup that I am trying to use for the element I want bound to the right hand side of the GUI is:
<Button Style="{DynamicResource NoChromeButton}" Click="referThis" Margin="0, 0, 0, 0" HorizontalAlignment="Right" >
<TextBlock>Button XYZ</TextBlock>
</Button>
However, setting the HorizontalAlignment to Right, doesn't actually move the text button to the right- it's still bound to the left hand side of the display... The only way I have found of moving it towards the right, is to set a large value for its 'x' position, i.e. Margin="900, 0, 0, 0", but then the position is not relative to the size of the window, so if I drag the right hand edge too far to the left, that button is outside the displayed area of the window, so I can't see it...
How I can I set the property of the button so that its position is relative to the right hand edge of the display window?
Edit
All of the elements in question are displayed inside the same <Grid> and <StackPanel> tags, i.e.
<StackPanel>
<Grid ...>
<Button ... HorizontalAlignment="Left">
</Button>
...
<Button ... HorizontalAlignment="Right">
</button>
...
</Grid>
...
</StackPanel>
The basic idea of the following solution is the Grid.
Create a ColumnDefinition with fixed width for each element you want aligned to the left, and a ColumnDefinition with fixed width for each element you want aligned to the right. On the middle, create a ColumnDefinition with a Width="*", so WPF first calculates the size of the other columns, based on their fixed length, and then it fills the remaining space with the middle-column.
Remember that each button has to set the Grid.Column property correctly to declare the column it wants to belong to.
As you resize the Window, the Grid updates its layout and the flexible children. In this case, the only flexible child is the middle-column.
Here's a simple implementation:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="10"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Content="Button1Left"/>
<Button Grid.Column="1" Content="Button2Left"/>
<Button Grid.Column="3" Content="Button1Right"/>
<Button Grid.Column="4" Content="Button2Right"/>
</Grid>
For more complete tutorials about the Grid control, check this, this and this.
Notice that I've set a simple style for the buttons with certain dimensions and margins only to make clear the result, but you can use your own style.
It would be good to know the container including the button (grid, panel, others?):
Anyway If you put:
<Button HorizontalAlignment="Right"
in
<StackPanel Orientation="Horizontal">
It should work... Check too if there is no contradiction bring by the style...

How to make text wrap in a WPF TreeViewItem?

This time, my question is as simple as it sounds... how do you get text to wrap in a WPF TreeViewItem?
I have a simple HierarchicalDataTemplate with just one TextBlock in it.
<TextBlock Text="{Binding Value}" TextWrapping="Wrap" />
The text does not wrap.
I tried binding the Width of the TextBlock to the ActualWidth of the TreeView, but although that makes the text wrap, the Width of the TreeViewItem does not fit in the TreeView because the TreeView has Padding. Binding to the ActualWidth of the TreeViewItem has (unsurprisingly) the same effect. Another downside to this is that even the items with little text stretch outside the TreeView bounds.
<TextBlock Text="{Binding Value}" TextWrapping="Wrap" Width="{Binding ActualWidth,
ElementName=TreeView}" />
Surely there must be a better way, like somehow informing the TreeViewItem of the TreeView's bounds... I can't believe it doesn't know automatically. But how can I do this?
UPDATE >>>
Thanks to H.B.'s answer, I managed to change the Grid.ColumnSpan to 2 on the Bd Border he mentioned in the ControlTemplate and it set the width so that the text now wraps nicely. The problem is that I am using this ControlTemplate for other TreeViewItems in other TreeViews where I don't want full width items.
The solution I came up with is simple. I have bound the TreeViewItem.Tag value to the Grid.ColumnSpan property in the ControlTemplate like so:
<Border Grid.ColumnSpan="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"
Name="Bd" Grid.Column="1" ... />
This allows me to change the Grid.ColumnSpan and therefore the full width or ordinary width behaviour of the TreeViewItem by setting the TreeViewItem.Tag value to either 2 or 1 respectively.
If you look at the default template of TreeViewItems you will see a Grid like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ... -->
As you can see the third column takes all available space while the others are on Auto, the header is placed in the second column inside a border:
<Border Name="Bd"
Grid.Column="1"
...
This means that the column will become as large as the header, there is no restriction on it. Thus the header just gets bigger than the TreeView itself.
If you add Grid.ColumnSpan="2" to this Border it will occupy the third column as well, which is restricted by how much space is left, hence the text will wrap; this will however extend the header across the whole width which might look a bit odd when selecting it.
Of course you will also need to disable horizontal scrolling:
<TreeView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ...

Unknown clipping around Border

I have a Grid layout. In one row, I have a Border and inside it a ToggleButton(with negative left margin so that it appears half outside the border). I've added DropShadowEffect to the border. Something seems to be clipping the shadow effect and the togglebutton outside the border. Please refer to the code and the image below.
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="140*" />
<RowDefinition Height="500"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="LightGray">
<Border Background="{StaticResource BorderFill}" Height="150" Width="400" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="20,0,20,10" BorderBrush="#FF999999" BorderThickness="1">
<Border.Effect>
<DropShadowEffect Color="Gray" BlurRadius="40" ShadowDepth="0.1"/>
</Border.Effect>
<ToggleButton Click="MenuToggleButtonClick" Margin="-6.5,0,0,5" Style="{StaticResource ExpandCollapseButtons}" Width="Auto" Height="Auto" x:Name="MenuToggleButton" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
</Border>
</Grid>
The left red arrow shows where the button is getting clipped and the right red arrow shows where the dropshadow is getting clipped. What is going on? How can I fix this?
It appears that this clipping only occurs when there isn't enough space for the inner Grid plus its margin. I was able to reproduce the behaviour in your screenshot if I resized the browser window small enough.
In your case, it appears there isn't enough height. A similar effect happens if there isn't enough width.
I'm not sure why this border clipping is happening. However, I found that if
I added the attributes MinWidth="440" and MinHeight="160" (the width and height of the inner grid plus its margin) to the outer Grid, I could no longer reproduce the clipping no matter how small I resized the browser window in any direction.

WPF: Why does text and elements blur if I use dropshadow effect on a parent item

If I add a DropShadowEffect to an parent element the text of the child elements are blurred. Why?
<Grid>
<Grid.Effect>
<DropShadowEffect />
</Grid.Effect>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Background="White">Test</TextBlock>
</Grid>
Update:
with shadow
without shadow
The reason why the text is blurred is because Effects cause the elements and all sub-elements to be rendered into a Bitmap first. This means that sub-pixel rendering (ClearType) cannot take place and therefore the text appears lower-quality.
You can work around this by applying the effect to only parts of your visual tree. The parts that don't contain the text.
In your case you probably want something like this:
<Grid>
<Border>
<Border.Effect>
<DropShadowEffect />
</Border.Effect>
</Border>
<TextBlock Background="White">Test</TextBlock>
</Grid>
It may be a problem with subpixels.
Try to add UseLayoutRounding = "True" to the grid.
Try adding TextOptions.TextFormattingMode="Display" to the TextBlock as shown in WPF Blurry fonts problem - Solutions.
The effect might somehow increase the "bluriness" by e.g. moving the grid some fractions of a pixel or so.

Resources