I am trying to get the distance in pixel between the top of the control and the middle of my vertical scrollbar (not all the scrollviewer, only the bar you can drag to scroll the control).
I don't understand which property i should use.
This is the code i wrote:
double barHeight = /*to do*/;
double barUpperEdge = scrollViewer.VerticalOffset;
double distance = barUpperEdge + (barHeight/2);
Another question: which is the mesurament unit of scrollViewer.VerticalOffset? If it isn't in pixel what cast should i do?
You can calculate that value from the IScrollInfo Interface. The ScrollViewer Class implements this interface and exposes the relevant properties that you need to use. As far as I can remember, you need to utilise three properties:
ExtentHeight - Gets a value that contains the vertical size of the extent.
ViewportHeight - Gets a value that contains the vertical size of the content's viewport.
VerticalOffset - Gets a value that contains the vertical offset of the scrolled content.
To explain a little further, the viewport relates to the visible area of the ScrollViewer and the Extent represents the total size of the scrollable area. The VerticalOffset describes the amount that the scrollable content has been scrolled. Using these three values, you should be able to calculate your required values that relate to the ScrollBar. Try something like this:
double barHeight = ViewportHeight * scrollviewer.ActualHeight / ExtentHeight;
UPDATE >>>
Please note that it is generally bad practice to use constant values in your calculations. Microsoft have exposed many common properties for this very reason. In your case, I believe that you can make use of the SystemParameters.VerticalScrollBarButtonHeight property, although you may need to add something to accommodate Padding and/or Margin values:
double barHeight = ViewportHeight * (scrollviewer.ActualHeight - 2 *
SystemParameters.VerticalScrollBarButtonHeight) / ExtentHeight;
You know... I've just thought of something... you may even be able to get your required thumb Height from these SystemParameters... you could try the SystemParameters.VerticalScrollBarThumbHeight Property, although I don't think that it will work with custom ScrollBars.
Related
I have a list of objects which form a mathematical set. So I want to display them in an ellipse like this:
If I then add a new object, the ellipse should grow and the 6th element should be placed inside the ellipse.
I thought I could solve this problem with an iteration. At first place object1 and the Name of set and draw the ellipse. Secondly add object2 and let the ellipse grow, and so on.
But I already struggled to find a proper solution for the arrangement of the first step, not to mention the growth of the ellipse in the second step. My problem with the first step is, that the ellipse should be smaller when Name of set and object1 have a small string representation. And the ellipse should be bigger, if Name of set and object1 have a longer string representation.
Or did I get somewhere on the wrong track? Maybe there is already a (framework?) solution for this problem, which I overlook.
Create an integer property called MyCount.
Create integer constants OriginalWidth and OriginalHeight.
Create integer variables ScaledWidth and ScaledHeight.
When your set is created add mySet.Name.Count() to MyCount.
When you add an object, add myObject.SomeProperty.ToString().Count() to MyCount.
When you remove an object, subtract myObject.SomeProperty.ToString().Count() from MyCount.
When MyCount is changed, recalculate ScaledWidth and ScaledHeight - something like ScaledWidth = OriginalWidth * (MyCount * [insert number here])
In order to keep your ellipse in the correct perspective your Ellipse's Height and Width will be based on constant values multiplied by a scaling factor, which is MyCount. You need 4 integer values: OriginalWidth, OriginalHeight, ScaledWidth and ScaledHeight. OriginalWidth and OriginalHeight are integer constants defining the minimum width and height of your Ellipse. ScaledWidth and ScaledHeight are integer variables which your Ellipse's Height and Width properties are bound to.
Every time a new object is added or removed to/from your set the number of characters in its SomeProperty is added to MyCount. Every time MyCount changes it triggers the recalculation of ScaledWidth and ScaledHeight. Binding your Ellipse's Width and Height properties to ScaledWidth and ScaledHeight, and implementing INotifyPropertyChanged on these properties, should scale your Ellipse accordingly.
UPDATE
The algorithm posted here: http://programming.nullanswer.com/forum/11925 would appear to address placing your child elements within your parent ellipse. I've substituted ellipse for square/circle where appropriate:
Pick a random point inside the [parent ellipse] & instance a [very low Width/Height ellipse] at that point.
Grow the radius of that [ellipse] till it satisfies these criteria:
does not overlap any of the other chosen [ellipses].
does not extend outside the [parent ellipse].
Choose the [ellipse] if it satisfies these criteria.
I've been working on a proper slider for my C# WPF project.
I wanted to create a slider, with a background that indicates different parts of the process, by adding a different color to each section on the slider. Furthermore I wanted to add small indicators (like the default ticks, but custom shape and irregular position) to the background.
I achived this by creating a drawing brush and adding correspondingly colored rectangles. This seemed to work fine, but a small distortion was still present, so I investigated further and realized the following:
With slider.ActualWidth I get the width of the whole widget. So in order to create a background covering the actual "slider" part, I'll have to be aware of the distance from the widget to the actual slider. (See image)
I measured the distance in a very small window, in fullscreen and stretched on two screens. It seems this distance is always 5 pixels. I tried google and looked through the info WPF provides on its pages, but either I read over it, or there is no information on this.
Can I be sure this distance is always 5 pixels ? In there any place such information is kept ? Is there maybe another way, to determine the size of the slider itself?
Assuming you haven't tinkered with the Slider template you can just walk down the visual tree and check the ActualWidth of the track:
Border b = VisualTreeHelper.GetChild(slider, 0) as Border;
Grid g = VisualTreeHelper.GetChild(b, 0) as Grid;
Border track = VisualTreeHelper.GetChild(g, 2) as Border;
Console.WriteLine("Track ActualWidth: " + track.ActualWidth);
I'm working a 2d tile-editor, used Winforms and XNA(for the map rendering) and i have a problem with the custom scrollbar.
I would like to know the formula for calculating the map scrolling depending the position value of my scrollbar.
Let me explain
Actually, i have a functional code but is not exact.
Here is my calculation (is the problem):
(Point Map.PixelMapSize = map size in pixel)
hScrollBarMap.Minimum = 0;
hScrollBarMap.Maximum = 100;
hScrollBarMap.LargeChange = hScrollBarMap.Size.Width * 100 /(Map.PixelMapSize.X);
mapScrollCalcul = ((hScrollBarMap.Value - hScrollBarMap.Minimum) * 100 / (hScrollBarMap.Maximum - hScrollBarMap.Minimum)) * Map.PixelMapSize.X / 100;
Sorry, I do not know how to explain. I found it by making a lot of tests...
But, the mapScrollCalcul is the final calcul to be applied to map position display.
What is the exact calculation for this ?
I hope you understand, I'm not speak English, just little understand.
But I understand you. :) (programmation language is universal)
Thank you for reading and, maybe, future responses.
You are overcomplicating things.
First, you are setting your LargeChange value relative to your image, not your view, and your scroll.Maximum relative to... what, exactly?
On MSDN, they say:
User interface guidelines suggest that the SmallChange and LargeChange
properties are set relative to the size of the view that the user
sees, not to the total size including the unseen part. For example, if
you have a picture box with scroll bars displaying a large image, the
SmallChange and LargeChange properties should be set relative to the
size of the picture box, not to the size of the image.
Now, lets assume that your image is 1000x1000 and your view is 100x100, and you are scrolling vertically. Then:
myVscroll.Minimum=0;
myVscroll.Maximum=image.Height; //1000
myVscroll.SmallChange = 10; // here: view.Height/10 or other value that makes scrolling look smooth
myVscroll.LargeChange = 100; // in this example, this is set to view.Height
And finally:
mapScrollCalcul = myVscroll.Value;
I have an application where I need to dynamically build the content to a Canvas. Everything works just fine, but I am a little unsure of how I can set the y coordinates for the labels in the safest way. For example, I need to add three labels that are essentially lines of text. In Java Swing or C# GDI I would just query the the font for the line height and add that value to the y coordinate of the drawText command.
This is my code.
double y = 0.0;
_line1.Content = "Line1";
_line1.SetValue(Canvas.TopProperty, y);
_line1.SetValue(Canvas.LeftProperty, 0.0);
CanvasChart.Children.Add(_line1);
double textHeight = _line1.Height;
y += textHeight;
_line2.Content = "Line2";
_line2.SetValue(Canvas.TopProperty, 0.0);
_line2.SetValue(Canvas.LeftProperty, y);
CanvasChart.Children.Add(_line2);
This does not work because _line1.Height does not seem to be set to anything useful at this point. I suppose it has not rendered yet. The above code is in the loaded event for the window. ActualHeight does not help either.
Most code that I've seen seems to just set them to a hard coded value. That I suppose looks right on the developer's display, and you just hope looks good at other resolutions/DPI. In Swing and GDI I always had the best results finding out exactly how many pixels a string will be rendered at and using this to offset the next line.
You must call the Measure method, specifying an infinite available size. This will update the DesiredSize of the control:
_line1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
double textHeight = _line1.DesiredSize.Height;
Another easy way to achieve the desired effect is to put the labels in a StackPanel.
In Swing and GDI I always had the best results finding out exactly how many pixels a string will be rendered at and using this to offset the next line.
This is possible in WPF as well. The GlyphTypeface class provides the AdvanceWidths and AdvanceHeights properties for each character in a typeface. By using CharacterToGlyphMap, you can map a character to an index within the AdvanceHeights, and use that to determine the actual height of any character.
For a detailed example, see GlyphRun and So Forth.
I found this code (a loop) which can fit the total width of all ColumnHeaders to the width of a listview (of course if the ListView's width is large enough, otherwise there will be a horizontal scrollbar displayed).
foreach(ColumnHeader ch in myListView.Columns){
ch.Width = -2;
}
I've just tried changing the value -2 to some other values and it didn't work. I need an explanation on this code, why does it have to be -2 and not any other?
By the way, if possible do you know any other (standard?) way to do this (fit the total width of all ColumnHeaders to the width of a ListView)?
Your help would be highly appreciated!
There is no automatic way to do this beyond what you have found. This is documented at http://msdn.microsoft.com/en-us/library/windows/desktop/bb761163(v=vs.85).aspx though you can't see the value for LVSCW_AUTOSIZE_USEHEADER, it is -2.
In order to do this yourself, you need to react to the ListView being resized, and calculate the widths yourself. There is an event for the resizing. Then you use listview.ClientSize.Width - SystemInformation.VerticalScrollBarWidth for the total width to account for the scrollbar.