I need to get the dynamic Height and Width of my Viewbox
The hierarchy of my xaml is like this:
<Grid>
<DockPanel>
<Border>
<ViewBox/>
</border>
</DockPanel>
</Grid>
The Viewbox Width is on "Auto" and the Height is bound to a variable in my Controller.
The Class hierarchy is like this:
Xaml <--> Controller
(the xaml.cs is mostly ignored)
Now my problem is that even in the direct code-behind (xaml.cs), I get 0 as ActualWidth and ActualHeight. If I change the dimension of my mainwindow I don't even get the standard Width and Height not to mention the dynamic one.
If Code-Snippets or information are missing, please tell me.
Here is the image with the red border. You have to look closey at the bottom (a small red Border): enter image description here
Regards
Richard
What I have tried:
I tried to get the Dimensions within the Code-Behind:
Height/Width (Only get the standard Height and NaN for Width)
ActualHeight/ActualWidth (both are 0)
RenderSize.Height/RenderSize.Width (both are 0)
I also tried the solution in this post:
Getting current size of WPF controls
It was the reason why I used the RenderSize solution
I end this question because the mainquestion was answered.
It was answered in the comments from Kamil Solecki
Related
I have a DataGrid which users can drag and drop files into for them to be imported into the program. I wanted to add some user feedback for when this is happening, so I have put an overlay over the DataGrid when the user drags and drops. The current look of the overlay is this:
I don't like the way the overlay goes over the top of the DataGrid header. If possible, I'd like to confine the overlay to the content only. Does anyone know of some way I could do this? I know I could hard code the height of the header or perhaps create a custom control but the more lightweight/unobtrusive the solution the better in my opinion. Here's a diagram of what I want in case it wasn't clear:
More information: In my current implementation I simply have both the DataGrid and the overlay inside a Grid, and turn the opacity of the overlay on and off as needed. The skinny rectangle under my DataGrid is a loading bar. I'd prefer the overlay not to go over that either, although it doesn't in the current implementation so I don't think that's an issue.
Edit: Here's how I ended up solving it, it's pretty quick and dirty but it works.
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var header = WPFHelper.FindVisualChild<DataGridColumnHeadersPresenter>(FilesDataGrid);
// Include outside border in margin
var border = FilesDataGrid.BorderThickness;
Thickness margin = new Thickness(border.Left, border.Top, border.Right, border.Bottom);
margin.Top += header.ActualHeight;
OverlayGrid.Margin = margin;
}
There is nothing more "lightweight/unobtrusive" than setting the top-margin of the overlay element to the actual height of the header. So if you don't want to overcomplicate things, you could just set the Margin to a hardcoded value of 23.96:
<Grid>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="..." Binding="{Binding}" />
</DataGrid.Columns>
</DataGrid>
<Border Background="Silver" Opacity="0.5" Margin="0 23.96 0 0" />
</Grid>
The more flexible solution would be to write a behaviour that finds the DataGridColumnHeadersPresenter in the visual tree and set the top-margin of the overlay element to its ActualHeight.
I Need to crop and resize an Image in my WPF application as soon as the Picture is loaded.
So, my Basic Image has a VGA size (640x480), and I Need to crop the edges (top by 18 Pixels, bottom by 36 Pixels, left by 48 Pixels, and right by 24 pixels). The new image (which is 568 x 426 pixels) Need to be refitted into the original size (640 x 480 pixels) - basically it's like a digital zoomc that we're using in photography.
I've already found some sample code (Cropping whitespace from image in C#) - this is however a Little bit too complicated since I don't Need to detect the Whitespace on the image. Is there any simple algorithm just by using XAML to do this ?
Thanks in advance.
I think that you should be able to do that by using the Viewbox Class. From the linked page: Defines a content decorator that can stretch and scale a single child to fill the available space. You literally add one to your Window and set your Image as the contents and then you can set properties to control which part of the image it displays:
<ViewBox Width="500" Height="500" Stretch="Uniform">
<Image Source="Images/SomeImage.jpg" Width="300" Height="300"
Margin="-48,-18,-36,-24" />
</ViewBox>
Experiment with the different StretchDirection values and set the Margin to negative values to crop. There are examples in the linked page, but let me know if you need more help.
I have clipped an Image control in to a Border which contains it by referring this blog
Sample xaml Code
<Border Behaviors:ImageClip.ToBounds="True">
<Image Source="{Binding Image}"/>
</Border>
But how do i clip an Image Control into a Path / Shape [Like Star /Ellipse] .I have tried previous method.But it was not succeeded because path does not have Content Property so that we can't set Image Clip Behaviour to Path.
I have tried with ImageBrush Fill .But that could not fit into my case beacause i have to implement some behaviours like Pinch & Zoom on Image Control. So that am stuck.
Can anyone help me with any suggestion or samples?
Have you considered just taking a path / shape and setting the background or fill properties to an image brush?
See: How to Use an image as ImageBrush on a Line or Path in WPF
I am developing an application in WPF using C#. I am putting Images in a WrapPanel and showing inside a Grid with one more Border and using images in Buttons also. Problem is my Image control loosing its quality. I am not able to post my image here so I am simply describing here.
I used SnapsToDevicePixels="True" for the images but still it looks blurry.
Updated:
Here I shared the Image below:
I think what Markus told is the one way to resolve your issue and try by adding one more property in it RenderOptions.EdgeMode="Aliased" for each image I mean :
<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"/>
if you still not able to fix your problem then you can refer this http://blogs.msdn.com/b/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx to create a custom Bitmap class and apply on all Images which are creating trouble for you.
You can also see this Stack Overflow Question
SnapsToDevicePixels seems not working for bitmaps.
The NearestNeighbor options actually converts the bitmap and will end up with different one to the original bitmap.
In WPF 4, a property "UseLayoutRounding" on the FrameworkElement is introduced to solve this problem.
By setting this property to True on your root element, such as Window will align children elements on the edges of pixels.
<Window UseLayoutRounding="True">...</Window>
This works for me
<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor"</Image>
Set RenderOptions.BitmapScalingMode="NearestNeighbor" for each image. Alternatively see this question here on StackOverflow.
Edit:
Here is my sample code
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="661">
<WrapPanel>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/icoChip32x32.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/icoChip32x32.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/Presentation-Edit.png"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/Presentation-Edit.png"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
</WrapPanel>
</Window>
And this is my result:
Use UseLayoutRounding="True" property on the parent element if image is used as a content. In your case it is the Button.
I ran into a blurriness issue with image backgrounds caused by scaling and the solution was much simpler than you may think. While at first I wondered if it was being scaled up to a power-of-two texture size, the scaling actually matched the ratio of System DPI (96) : Image DPI (72, which is the default for many editors). If you adjust the image to 96 DPI it should display pixel-perfect with the default Windows settings.
EDIT: Tried an image with high detail contrast and it is slightly softened.
WPF doesn't use concrete pixel values for sizes and positioning, so that it can scale well with DPI.
This can lead to a problem where it tries to use a position that doesn't correspond to a discrete on-screen pixel; some of the image pixels are rendered over multiple on-screen pixels which we see as blurring.
UseLayoutRendering=true with SnapToDevicePixels=false should solve this issue. You also need to set it at the main window level too, so that the calculations cascade down to the image level.
You can try this out by creating a simple WPF application with one window, and your images. Setting the image margin to be something silly like (10.452, 0.736, 0, 0) will lead to blurring. This goes away with UseLayoutRendering=true on the image.
If you then set the margin again in your window's constructor after InitializeComponent(), it is blurry regardless of whether you set UseLayoutRendering=true on the image, since the calculations to line up with on-screen pixels were made before you then moved the image to a location which doesn't match up with these.
I'm not entirely sure what the difference is between UseLayoutRendering and SnapToDevicePixels - I think it is just the time that the calculations are made. UseLayoutRendering seems to be preferable for images.
Stretching/squashing an image from its original size can also lead to blurring problems.
I had the same Problem, but in my case I've downloaded Icons and found out, that they all had wrong DPI too... 110,56 and 116,xx and 95,99 etc...
When i changed the DPI to 96 for all, everything was fine!
The standard System.Windows.Forms.TabControl component draws a border around the TabPages it contains. If you set its Dock to Fill, these borders run up to the edge of the parent control, but they're still there, taking up screen space.
In Visual Studio, if you dock two windows in the same place, you get a TabControl-like set of tabs along the bottom, but no borders along the sides.
Is it possible to get a TabControl to display its TabPages in this manner, with no wasted screen space at the sides? If possible, I'd like to avoid solutions that involve painting the control myself.
Remove the height and width attributes from TabControl
Set horizontal and vertical alignment to stretch
e.g. won't stretch;
<TabControl Height="373" Width="609" HorizontalAlignment="Stretch" Name="tabControl1" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
e.g. will stretch;
<TabControl HorizontalAlignment="Stretch" Name="tabControl1" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
Instead of using the Dock property you should try using the Anchor to anchor each of the four sides. Then you need to position the TabControl so it is positioned a couple of pixels bigger on all sides that the parent. That way the borders are hidden because they cannot be drawn when behind the parent control.
Using the standard .NET tab control, this isn't directly possible. What is the ultimate goal for this? Are you trying to simulate the same type of tabbed-MDI style display as Visual Studio? If that's the case, there are several third-party solutions available - some open source and some commercial.
The other responses about using the Anchor property in combination with setting the size so it is just a bit larger than the actual window might work, but I think it might look a bit odd visually. It should work regardless of the theme and accessibility settings, but you may end up having to programmatically set the size to be a few pixels larger than the parent.
Is it possible to get a TabControl to display its TabPages in this manner, with no wasted screen space at the sides? If possible, I'd like to avoid solutions that involve painting the control myself.
If I understand your question correctly, and reading through the currently accepted answer, you want to know how to make the Tabs for a TabControl stretch across the whole Control with no wasted space like below:
To do this, set cTabControl.Dock = Fill, then make the following function and call it in Form1_Shown() and Form1_Resize(), or whatever "Resize()" functions you've created.
C#
void ResizeTabs()
{
int numTabs = cTabControl.TabCount;
float totLen = 0;
using(Graphics g = CreateGraphics())
{
// Get total length of the text of each Tab name
for(int i = 0; i < numTabs; i++)
totLen += g.MeasureString(cTabControl.TabPages[i].Text, cTabControl.Font).Width;
}
int newX = (int)((cTabControl.Width - totLen) / numTabs) / 2;
cTabControl.Padding = new Point(newX, cTabControl.Padding.Y);
}
VB
Sub ResizeTabs()
Dim numTabs As Integer = cTabControl.TabCount
Dim totLen As Decimal = 0
Using g As Graphics = CreateGraphics()
' Get total length of the text of each Tab name
For i As Integer = 0 To numTabs - 1
totLen += g.MeasureString(cTabControl.TabPages(i).Text, cTabControl.Font).Width
Next
End Using
Dim newX As Integer = ((cTabControl.Width - totLen) / numTabs) / 2
cTabControl.Padding = New Point(newX, cTabControl.Padding.Y)
End Sub
I solved the same problem by adding spaces to the tabs title:
var pageAlignment = 50;
TabPage1.Text = TabPage1.Text.PadLeft(pageAlignment / 2).PadRight(pageAlignment);
TabPage2.Text = TabPage2.Text.PadLeft(pageAlignment / 2).PadRight(pageAlignment);
TabPage3.Text = TabPage3.Text.PadLeft(pageAlignment / 2).PadRight(pageAlignment);
Anchor the left and right sides of the control with the width set to the width of the parent control.
childControl.Anchor = Anchor.Left|Anchor.Right;
childControl.Width = parentControl.Width;
<Grid>
<TabControl Name="tabControl1" >
<TabItem Header="tabItem1" Name="tabItem1">
<Grid />
</TabItem>
<TabItem Header="tabItem2" Name="tabItem2">
<Grid />
</TabItem>
<TabItem Header="tabItem3" Name="tabItem3">
<Grid />
</TabItem>
</TabControl>
</Grid>
Do not Dock the TabControl. Stretch it out on the designer so its left and right edges extend beyond the window.