Blur images no matter what in WPF - c#

I have a button with an image and no matter what I do the image looks blurry after rendered/compiled.
FYI - The image looks good when not in WPF controls
The image on the left is before compiled, the image on the right is blurry after compiled.
I tried applying UseLayoutRounding, applying SnapsToDevicePixels,
RenderOptions.BitmapScalingMode and removing the antialiasing directly in the button and directly to the image but nothing.
Any idea how can I improve the quality of the images in WPF?
XAML:
Styles applied directly to the button:
<Grid>
<Button x:Name="recentButton" UseLayoutRounding="True" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" RenderOptions.EdgeMode="Aliased"
Margin="10,137,302,10"
Width="auto"
Height="23"
HorizontalAlignment="Stretch"
BorderBrush="{x:Null}"
Foreground="White"
BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Image Source="/Tool;component/Design/Images/more-icon-active.png" Stretch="None"/>
</Button>
</Grid>
Styles applied directly to the image:
<Grid>
<Button x:Name="recentButton"
Margin="10,137,302,10"
Width="auto"
Height="23"
HorizontalAlignment="Stretch"
BorderBrush="{x:Null}"
Foreground="White"
BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Image Source="/Tool;component/Design/Images/more-icon-active.png" UseLayoutRounding="True" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" RenderOptions.EdgeMode="Aliased" Stretch="None"/>
</Button>
</Grid>

The problem is you're using UseLayoutRounding on the control directly.
But, be aware of this note in the linked documentation,
You should set UseLayoutRounding to true on the root element. The layout system adds child coordinates to the parent coordinates; therefore, if the parent coordinates are not on a pixel boundary, the child coordinates are also not on a pixel boundary. If UseLayoutRounding cannot be set at the root, set SnapsToDevicePixels on the child to obtain the effect that you want.
Therefore, use it on the parent container instead. In your case, that would be on the on the <grid> element.
Other recommandations
Recommended by #Clemens in the comment section,
Depending on the kind of image, RenderOptions.BitmapScalingMode="NearestNeighbor" may add some sharpness.
Note that you will have to apply that on the image directly.
Recommended by #BradleyUffner in the comment section,
Setting TextOptions.TextFormattingMode="Display" on your top level elements to greatly improve text rendering on desktop computers.

Related

DropShadowEffect with Semi Transparent Grid

I am trying to create a grid (with 30% opacity) and drop shadow from it. I have done a mock up in photoshop and this is what I want to achieve:
This is how I tried to implement it in xaml:
<Grid Background="#808080">
<Grid Width="100"
Height="100"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid Background="White"
Opacity="0.3">
<Grid.Effect>
<DropShadowEffect />
</Grid.Effect>
</Grid>
</Grid>
</Grid>
Unfortunately, this is how it turned out:
As you can see from the image above, the shadow effect can seen underneath the 30% grid. How do I remove the shadow effect within the grid and only make the shadow appear outside the grid (on the bottom right)?
Easy solution, drop the opacity. But I guess that would not be acceptable, so another solution which is more of a workaround.
Add a Border inside your inner grid and drop shadow on that border, also make the border thickness disappear on 2 sides on which you do not want the shadow. Something like this:
<Grid Background="White" Opacity="0.3">
<Border BorderBrush="White" BorderThickness="0,0,1,1">
<Border.Effect>
<DropShadowEffect />
</Border.Effect>
</Border>
</Grid>

How to Fill SolidColorBrush/Ellipse [duplicate]

I am trying to create this in WPF (I realize I could just use an image, but I am trying to learn WPF):
(source)
This is what I have so far but it isn't producing the desired result, in that, the textbox seems completely hide the ellipse whereas it should simply have a transparent background:
<StackPanel>
<TextBlock HorizontalAlignment="Left" Margin="144,207,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Left" Height="52" Margin="142,189,0,0" Stroke="Black" VerticalAlignment="Top" Width="52"/>
</StackPanel>
You can put things like this in a viewbox to make scaling easier, something like this. You'll need to remove the stack panel, it's going to stack items one on top of the other which isn't what you're after here. I used a grid in this case.
<Viewbox Width="100" Height="100">
<Grid Width="20" Height="20">
<Ellipse Stroke="Black"/>
<TextBlock HorizontalAlignment="Center" Text="i" TextAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Viewbox>
Or you can use the unicode character: ⓘ
code 0x24D8
<TextBlock Text="ⓘ" FontSize="52" />
So a stackpanel will place the first item at the top, the second just below it, third below the second, and so forth. What you could do is use a Canvas or a Grid. Like the stackpanel, they are "Content Controls" and support placing multiple objects inside of them like you have done with the stackpanel.
So a really quick way to do what you're trying to accomplish would be:
<Grid >
<Ellipse HorizontalAlignment="Left" Height="52" Stroke="Black" VerticalAlignment="Top" Width="52"/>
<TextBlock Text="i" FontSize="52" Margin="18,-13,-6,13" />
</Grid>
You can do it using a border and a TextBlock. A square border will become a circle if you make its CornerRadius equals half its Width (or Height):
<Border Width="100" Height="100" CornerRadius="50" BorderBrush="Black" BorderThickness="2">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="50" Foreground="Blue" >i</TextBlock>
</Border>
Don't use a StackPanel for this, the purpose of it is to stack things, not show them overlapped, you're using the wrong tool for that. Use a Grid, it's far more suited for what you're trying to do.
To have a transparent background, you have to either set the TextBlock's Background property to Transparent, or set a null background.
Background={x:Null}

WPF How to make a Viewbox aware of its available space from within a StackPanel

I have a custom WPF control based on Soroosh Davaee’s ImageButton example at http://www.codeproject.com/Tips/773386/WPF-ImageButton. The custom control combines an Image and TextBlock in a horizontal StackPanel within a Button. (BTW, to get Soroosh’s example to run, I had to edit the solution properties so that “SampleView” is the startup project rather than “ExtendedButton” being the startup project.)
I want the text in the TextBlock to automatically shrink if necessary to avoid clipping at the right edge if the text is too long to fit naturally in the button. For example, if I edit Soroosh's MainWindow.xaml to make the button text too long to fit...
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
...the result is the following buttons with clipped text:
In researching this, it seems the simplest way to auto-shrink the content of a TextBlock is to wrap it within a Viewbox:
<Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock ... />
</Viewbox>
DownOnly apparently prevents the Viewbox from enlarging the text to fill the space, and Fill (as opposed to Uniform) seems to tell it to stretch (shrink) only the dimension that needs to shrink (i.e. the horizontal dimension in my case).
In Soroosh's example Generic.xaml file, I wrapped the TextBlock in such a Viewbox:
<Button >
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
I added--> <Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
I added--> </Viewbox>
</StackPanel>
</Button>
This produced exactly the same clipped button text. Just experimenting, I tried forcing the Viewbox to have a fixed width...
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
...which produced this:
...which shows the capability of the Viewbox, if only it could somehow know its available width when it's inside the StackPanel.
I did note that if I wrap the Viewbox around the whole StackPanel, it successfully auto-shrinks the entire content of the StackPanel:
<Button >
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
</StackPanel>
</Viewbox>
</Button>
...which produces very nearly what I want:
...but both the image and text are shrunk, and I want only the text shrunk.
How can I make the Viewbox, wrapping only the TextBox, know its available width (and height, I suppose) from within a cell of the StackPanel?
This is a common problem. The solution is simply to not use a StackPanel to do any kind of layout that requires re-sizing of child controls. It's simply not the correct Panel for the job. Instead, try using a Grid panel, which will resize its child controls. The StackPanel control is really only good for the most basic of layout duties... try anything more adventurous and you'll find yourself getting these issues.
One other alternative is to use the TextBlock.TextTrimming Property to trim the text instead... you could put the full text into a ToolTip too.

Webbrowser is showing corners in rounded border

I have following code -
<Border Grid.Column="1" Grid.Row="1" Name="mask" CornerRadius="20" Height="auto" Width="auto" BorderThickness="1"
BorderBrush="Black">
<WebBrowser Name="webBrowser" Source="http://www.google.com" Margin="1" />
</Border>
It is providing the rounded boundry, but the webbrowser contant is still showing corners. I want to clip the extra corner to the boundry.
Unfortunaly the WPF WebBrowser isn't a proper WPF Control, even though it's in the System.Windows.Controls namespace. It's just a wrapper around the IE ActiveX Control. So you cant apply styles, clip its corners, change the Control Template, etc. All WPF can do with the WebBrowser is change its size and position.
I think there are some hacks out there, but it definitively wont be as easy as setting a property.
Ok. So as far as I remember, UIElement has Clip property so you can specify an element to clip
<WebBrowser Name="webBrowser" Source="http://www.google.com" Margin="1">
<WebBrowser.Clip>
<Border Grid.Column="1" Grid.Row="1" Name="mask"
CornerRadius="20" Height="auto"
Width="auto" BorderThickness="1" />
</WebBrowser.Clip>
</WebBrowser>

How to place a slider over on top of a videobrush

I am attempting to create a slider control which will determine the scaletransform of a videobrush in my MainPage, and was wondering if it was possible to somehow place this slider on top of the videobrush (which I would like to be full screen)? Currently I am using a grid for my layout where a videobrush takes up the whole screen except for two buttons on the bottom of the screen, but I would like to possibly use a canvas and place this slider in a way that would account for the current and future screen sizes of a Windows Phone device. I am unsure of how to exactly accomplish this without setting constant dimensions for the slider. For instance the slider may be placed horizontally near the bottom of the screen in Portrait mode and would have a 50 pixel space between the left and right sides. Could someone assist with how this could be done?
EDIT
Placing a single child element over the videobrush works, although I would like to place more than one slider which gives an error. I also wanted to add information above and below each slider so I chose a stackpanel to do this (yet only one stackpanel as a child element is allowed?).
<Border x:Name="videoRectangle" Grid.Row="0" Grid.ColumnSpan="2" >
<Border.Background>
<VideoBrush x:Name="viewfinderBrush">
<VideoBrush.RelativeTransform>
<CompositeTransform x:Name="viewfinderBrushTransform" CenterX=".5" CenterY=".5" Rotation="90" />
</VideoBrush.RelativeTransform>
</VideoBrush>
</Border.Background>
<!--<StackPanel VerticalAlignment="Top">
<TextBlock x:Name="resolutionValueTextBlock" HorizontalAlignment="Center" Text="{Binding Value, ElementName=resolutionSlider}"/>
<Slider x:Name="resolutionSlider" HorizontalAlignment="Stretch" Margin="50,5,50,5"/>
<TextBlock x:Name="resolutionTextBlock" HorizontalAlignment="Center" Text="resolution"/>
</StackPanel>-->
<StackPanel VerticalAlignment="Bottom">
<TextBlock x:Name="zoomNumberTextBlock" HorizontalAlignment="Center" Text="{Binding Value, ElementName=zoomSlider}"/>
<Slider x:Name="zoomSlider" HorizontalAlignment="Stretch" Margin="50,5,50,5"/>
<TextBlock x:Name="zoomTextBlock" HorizontalAlignment="Center" Text="zoom"/>
</StackPanel>
</Border>
If possible I would like both stackpanels to be available, but if not I guess I would have to use the bottom one only.
Stay with the Grid:
<Grid>
<Rectangle>
<Rectangle.Fill>
<VideoBrush ... />
</Rectangle.Fill>
</Rectangle>
<Slider HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Margin="50,5,50,5"/>
</Grid>

Categories