Image control in WPF Stretches Image When Stretch Set to None - wpf

I have an image control inside a grid displaying a 16x16 icon. But for some reason even though I set the properties so it would remain 16x16 it looks stretched.
Code :
<UserControl x:Class="ChatControls.UserListItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="28" d:DesignWidth="132">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" MinWidth="24" MaxWidth="24" />
<ColumnDefinition Width="171*" />
</Grid.ColumnDefinitions>
<Image Name="imgIcon" Source="/ChatControls;component/Images/NormalUser.png" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" />
<Label Content="Muhammad[A]" Grid.Column="1" Name="lblNick" VerticalContentAlignment="Center" Padding="8,5,5,5" />
</Grid>
</UserControl>
Is there any reason for this?
UPDATE 1:
Yes at runtime also :(
Many thanks in advance.

Actually, I've seen that regularly with PNG images. It seems that the default resolution for PNG is 72dpi, while the default screen resolution in WPF is 96dpi. WPF tries to take this into account by rendering png bitmaps scaled to 133% of their pixel size, which is technically correct but normally not what the user wants. You can either use a gif or jpg instead, or you can combine the image with a LayoutTransform scaling it to 0.75 of its size, or just stick with setting the size of the image control explicitly.

I find I often have to explicitly specify the Width and Height of Image controls to get them to appear correctly:
<Image
Name="imgIcon"
Source="/ChatControls;component/Images/NormalUser.png"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Height="16"
/>

First of all, your XAML definition of your 171* is a bit odd. Your best approach is to do this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
You need to look into XAML layout passes in order to understand what this is doing.
Secondly, because you're using a dynamic image source (loaded as a URI), it will be streamed so the width during the first layout pass will be 24, but after the image has been streamed, the control will resize dynamically. If you want to enforce sizing, your best bet is to use a border around the image as a 0 width container. Like this
<Border Grid.Column="0" Grid.Row="0" BorderThickness="0" BorderBrush="Black">
<!-- UniformToFill: Scale to completely fill output area.
Aspect ratio is preserved. Cropping may occur.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="UniformToFill" />
</Border>
Enforcing a width and a height around an image is a shorthanded way of doing this. The other thing you may want to do is to explicitly define the way the source image is loaded like this:
<Image Width="200">
<Image.Source>
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
Which will not load the full image but will resize before load as opposed to dynamically. For further reference review http://msdn.microsoft.com/en-us/library/ms748873.aspx
I agree with the accepted answer, but I don't think it explains why, it just explains that it works.

It happens because of the image pixels that is dependent on the screen resolution, it should be device independent so that to remains same on any screen resolution
So use this to do so.
<Image Width = "24" Height = "24" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased" Stretch = "None"/>
replace Width and Height with the original size of the image
This'll help you

Related

Changing Height of ScrollViewer Content dynamically through code

I'm stuck at a point where I have to change the height of scroll viewer content irrespective of the size the contents inside it need.
The reason is that I will have a very long Image and I don't want to slow my GUI while scrolling. So,I cut the long image and I render stitched images of it depending on current scrollviewer vertical offset.
I tried to achieve it by putting a Hidden Long image so that it won't render on scroll and there won't be any lag. But I don't feel good about it.
Can someone help me to dynamically increase the ScrollViewer content Height?
The code is here:
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="9" Grid.RowSpan="12" Margin="10,60,10,0" >
<Image x:Name="StitchedImage" SnapsToDevicePixels="True" HorizontalAlignment="Stretch" Stretch="Fill"/>
<ScrollViewer x:Name="ImageScrollViewer" Background="Transparent" ScrollChanged="ImageScrollViewer_ScrollChanged" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" >
<Image x:Name="longImageHidden" SnapsToDevicePixels="True" Visibility="Hidden"/>
</Grid>
</ScrollViewer>
</Grid >
I think It would be really cool if I can just give a blank image specifing just height and width without any source. Is that even possible?
Yes, it is:
<Image Height="1000" />
You could also set the Height of a ScrollViewer and any other FrameworkElement derived type.

Setting Width of control relative to screen resolution in silverlight

I am unable to set the size of border control relative to screen resolution.
I want to specify width of Border to 80% of the screen resolution [width wise only]. But I am unable to do so.
The easiest way would be to put your border in a Grid:
<Grid x:Name="LayoutRoot"
Background="White">
<Grid.ColumnDefinitions>
<!--80% column-->
<ColumnDefinition Width="8*"></ColumnDefinition>
<!--20% column-->
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
Background="Red"></Border>
<Border Grid.Column="1"
Background="Yellow"></Border>
</Grid>
EDIT:
Sorry, I just realised I did not read your question properly. You are talking about screen resolution. My example sets the first column of the grid to 80% of the browser window size. If it is screen resolution you want I think you will have to use javascript to get the values and then use code to set your object to the correct size:
var width= HtmlPage.Window.Eval("screen.availWidth");
var height= HtmlPage.Window.Eval("screen.availHeight");

Putting Canvas Inside Viewbox in Silverlight With Image

All,
I'm trying to make the silverlight app I'm making resize in a reasonable manner. To do this, I thought I would use a dynamic grid. In the center of the grid I need to put an image inside of a canvas because I will dynamically be positioning objects on top of it. Ideally, as the user makes the browser window larger, the center column would be able to resize and grow larger, thereby growing the image.
Here's what I've got:
<Viewbox Grid.Row="0" Grid.Column="1">
<Canvas x:Name="cvsCenterPane">
<Image x:Name="imgFormImage" MouseLeftButtonDown="imgFormImage_MouseLeftButtonDown"
MouseLeftButtonUp="imgFormImage_MouseLeftButtonUp" MouseMove="imgFormImage_MouseMove" />
</Canvas>
</Viewbox>
In the code behind, I then set the image source.
Here's my grid definition:
<Grid x:Name="LayoutRoot" Background="DarkCyan" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
I think there must be some sort of unhandled exception occurring during the construction of the Viewbox because the image does not display at all. What am I doing wrong here? Am I taking the wrong approach?
There is no exception, the canvas just does not have any set dimensions which is a requirement when you want to use a ViewBox.
I for one would not use a canvas, you can stick with the grid since you can place more than one control in a cell and if you need to move the objects around you can use the Margin or a TranslateTransform in the RenderTransform property.
This does not work because you cannot set the x:Name attribute of children in a Viewbox with silverlight. At least according to a few sources:
http://blog.ningzhang.org/2008/11/viewbox-control-in-silverlight-toolkit.html
http://forums.silverlight.net/forums/p/48535/128830.aspx
http://forums.silverlight.net/forums/p/45789/123941.aspx#123941
this seems to be by design. A few workarounds have been suggested, so I will try them.
Edit: HB seems to be correct, there is no exception, the Canvas needed to have dimensions set.

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.

UserControl Dimensions Ignored in MainPage Layout

I have a Canvas with a Grid on it. The Grid contains 3 columns. The first column contains another Grid, the second contains nothing, the third contains an Image (a box). (I have the blank column for animation purposes unrelated to this question.)
In my child Grid I have 2 rows. The first row contains a UserControl (shelves of boxes), the second contains an Image (a barcode).
The problem is that the layout engine seems to completely ignore the dimensions of the user control. In the preview I see my UserControl and directly on top of it the two other images. Granted Canvas doesn't automatically size its children, but I have that resolved with some resize statements in the SizeChanged event of the page.
As it is, the box shows up at runtime in the bottom right corner of my window as it should, however the barcode appears positioned as if the UserControl doesn't exist.
For an illustration of my issue please see http://www.wynright.com/temp/Problem.png
The following is my XAML code:
<Canvas x:Name="MainCanvas" Background="Silver">
<Grid Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Name="LayoutChild" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<LightPickDemo:Picker x:Name="PickZone" ZoneCleared="PickZone_ZoneCleared" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Image Name="BarCode" Source="/LightPickDemo;component/Images/BarcodeScan.png" HorizontalAlignment="Center" Stretch="None" VerticalAlignment="Center" Grid.Row="1" />
</Grid>
<Image Name="imgShippingBox" Source="/LightPickDemo;component/Images/Empty-Box.png" VerticalAlignment="Bottom" Stretch="None" Grid.Column="2" />
</Grid>
</Canvas>
So I wonder what do I need to do to get the UserControl to offer its size for the layout engine. I can see in my designer the size of the control, so clearly the compiler knows that there is size to this control.
I would like the barcode to show centered below the UserControl.
Here is the XAML for the UserControl:
<Canvas>
<Image Name="ImageBase" Source="/LightPickDemo;component/Images/BayShelves.png" />
<LightPickDemo:ZoneLight x:Name="ZoneLight" Canvas.Left="345" Canvas.Top="0" ButtonPress="ZoneLight_ButtonPress" />
<LightPickDemo:PickerModule x:Name="pickerCalculator" Canvas.Left="74" Canvas.Top="266" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerCalendar" Canvas.Left="207" Canvas.Top="266" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerPaperClip" Canvas.Left="521" Canvas.Top="266" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerRuler" Canvas.Left="649" Canvas.Top="266" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerScissor" Canvas.Left="75" Canvas.Top="532" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerStapler" Canvas.Left="250" Canvas.Top="532" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerStapleRemover" Canvas.Left="435" Canvas.Top="532" OnPicked="Picker_PickChanged" />
<LightPickDemo:PickerModule x:Name="pickerTapeDispenser" Canvas.Left="635" Canvas.Top="532" OnPicked="Picker_PickChanged" />
</Canvas>
Most likely the ActualHeight of your user control is zero. Looking at your XAML for the user control you should be able to just set Height and Width in the XAML of the user control.
I can't determine what is the UserControl from your image, but if you set the property to 'collapsed' the engine won't read the size I don't think. If the UserControl isn't visible, but you want to show the dimensions, animate the opacity property instead of visibility. The barcode is in Row 1 which is the top row, should it be in row 2?
Am I correct in assuming the barcode needs to be below the image with the 2 rows of boxes? Where is the UserControl? What is it?
An answer to my question seems to be to put the following code in my UserControl, however, I can't imagine this is the best answer and I know it doesn't allow for screen scaling at all. So please, if anyone knows how to do this correctly, please let me know.
Thanks to Wallstreet Programmer for leading me to this workaround.
Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
Dim bmp As BitmapImage
bmp = BaseImage.Source
Return New Size(bmp.PixelWidth, bmp.PixelHeight)
'Return MyBase.MeasureOverride(availableSize)
End Function

Resources