Constraining windows wpf - c#

I have a window that needs to be constrained within another window. In order to do this,
I hook into the SizeChanged event on the top level window....and in that event I need to adjust the second window so that it is aligned to the nearest edge only if there is an intersection between the two i.e if the smaller window gets outside the boundary of the bigger window.
I do a lot of math calculation to get this...and im still not near to the solution!
Im having trouble doing this because it involves a lot of messy code I was wondering if any of you guys had an easier solution to this?
Basically im dealing with 2 rectangles and I need to ensure that when the size of the bigger rectangle changes...if there is an intersection between the two, then the smaller rectangle should align itself to the edge of the bigger rectangle so that the smaller rectangle is within the bigger rectangle.
Could be a simple math problem in C# forms?
Any suggestions are welcome thanks!

For both windows you need to get the x and the y coordinates of the location of the window in systemcoordinates.
How to do this in wpf can be found here http://blogs.msdn.com/b/llobo/archive/2006/05/02/code-for-getting-screen-relative-position-in-wpf.aspx
Next you need to have the two windows react on each others sizechanged events so that the one window gets notified when the others size has changed.
Then the following math will do the job:
(assuming window 1 is currently in the bounds of window 2 and window 2 size changes and you want to actually resize the window instead of moving it when possible)
//PSEUDOCODE
//Case1 (left bound changes)
if(window2.x > window1.x)
{
window1.x = window2.x;
}
//Case2 (top bound changes)
if(window2.y > window1.y)
{
window1.y = window2.y;
}
//Case3 (right bound changes)
if(window2.x + window2.width < window1.x + window1.width)
{
window1.width = window2.x + window2.width - window1.x;
}
//Case4 (bottom bound changes)
if(window2.y + window2.height < window1.y + window1.height)
{
window1.height = window2.y + window2.height - window1.y;
}

Related

Dynamical rectangle plot c# wpf

I want to create a plot that dynamically displays active elements as rectangles. I have achieved a first version that is actually ok using OxyPlot.Annotations.RectangleAnnotation which I add to myPlotModel.Annotations, you can see it in the image hereafter:
Example of wanted display
The thing is that after a while, the amount of drawn rectangles make the update not smooth as I update the shown timewindow (which is set to 15 seconds). I have already set a maximum of drawn elements that suffice to cover the displayed window (i.e. the rectangles get removed as they are too far in the past), but the rendering is still jerky. I draw the rectangles by allocating them to an equal fraction of the Y-axis, that is the third one from the top gets:
rowNumber= 3.0
minimumY = maximalY - maximalY / totalElements * rowNumber
maximumY = maximalY - maximalY / totalElements * (rowNumber + 1.0)
And the Y-axis is hidden.
My question:
Is there a smarter way of creating such a display that would be less computationally heavy, and therefore allow a smoother update? I do not have to stick to OxyPlot, it is simply the easiest way that I found to obtain what I wanted.
Thanks for your answers!
Technically, the answer to your question is "Yes".
There are a number of ways to do this.
You could have a vertical itemscontrol that had an itemscontrol in it's template. That could have a canvas as it's itemspresenter and you could bind canvas.top and canvas.left to properties in it's content. Template each into a rectangle and bind height and width.
And of course do something about the scale on the bottom and the column of activity labels or whatever you want to call them there.
Unless you're using an absolutely ancient machine, that'd just fly.
It's quite a lot of work but it would probably be quicker to write that than to search through a load of alternative packages and decide which was optimal.

Textbox Positioning Issues On Form Bigger Than Resolution

I have this form that works perfectly fine on resolution 1920 x 1080 (mainly cause I made it using that resolution). I read information about controls from a database (labels and textboxs). This information tells me where to place the controls. Like I said, on 1920 x 1080 everything is placed correctly. When I go down resolutions the form is now bigger than the resolution so I added scroll bars. Issue is that the controls are being placed as if the form that is visable on the screen is all that there is. So if I were to place a textbox at location (4, 90) on the form on lower resolution it might place it at (100,90). Y coord is fine, X coord is not.
Although TableLayoutPanels looks very nice in this case it would be a complete hassle and a waste of time to basically completely redo what I have done already. If I were to have started fresh I probably would have used TableLayoutPanels. Instead what I did was, since the Form was bigger than the resolution, I turned my forms AutoScroll to true (which I said in the question). I then set the AutoScrollPosition to (0,0) on form_shown which makes the horizontal one go to the left and the vertical one to the top using...
this.AutoScrollPosition = new Point(0,0);
Since the controls information is based off of where they are on the screen I just force the form's top left to be located in the top left of the screen and not off. I also had to have an override for the ScrollToControl. Every time a control was placed it would reset back to the center and would mess the placement up. So I added this...
protected override Point ScrollToControl(Control activeControl)
{
return this.AutoScrollPosition;
}

Winrt - Adjusting flyout according to where it appears

I have a GridView in a windows store project, that contains some big squares, and inside those i have a list of user images, when i tap on of those images a flyout appears on the right showing some information like this.
the problem is that my gridview extends to the edges of the screen and beyond, and when that does i get this situation, i press the user with the red border near the edge of the screen and flyout appears on left.
My flyout placement is set to Right, and im guessing since the element i press is near the edge it follows the Fall back order with according to this is Right > Left > Top > Bottom.
What i would like to know is how to detect this happens, so i can adjust my flyout position, or another viable alternative :)
After searching through properties and Dependency properties on Flyout and FlyoutBase, I haven't found a way to simply get the actual placement of the Flyout (which is unfortunate because I think that can be important, as we see in your case). Perhaps you can try what was proposed here by implementing a method that compares the desired size of the Flyout with the available space.
You can subscribe to FlyOut.Opened event and compare absolute coordinates of the flyout and the element you're showing it at. Here is an example for top/bottom flyout placement (easily extendable to check for left/right as well):
private void FlyOut_Opened(object sender, object e)
{
GeneralTransform flyOutTransform =
flyOut.Content.TransformToVisual(Window.Current.Content);
Point flyOutPosition =
flyOut.TransformPoint(new Point(0, 0));
GeneralTransform showAtElementTransform =
showAtElementTransform.TransformToVisual(Window.Current.Content);
Point showAtElementPosition =
showAtElementPosition.TransformPoint(new Point(0, 0));
if(flyOutPosition.Y < showAtElementPosition.Y)
{
// top
}
else
{
// bottom
}
}

How to align windows when they are very near

I have an application with some small windows on the screen. I would like to align them to each other, so when I move one close enough, it will automatically be align with the other. Helping me positioning and size them all.
How can I know the position of other windows when there isn't a parent window? Is it possible to know it even if they are different process (applications)?
I am not fully sure what you mean but the following trick is what I use for dynamic layout and it gives me full control over anything, you just need to play around with it and you can easily get the distance between two windows.
This code is copied from a windows phone app but it is easily understood.
width = Convert.ToInt32(Window.Current.Bounds.Width);//gets window width
height = Convert.ToInt32(Window.Current.Bounds.Height);// gets window height
double dist Math.Abs(Btn1.GetValue(Canvas.LeftProperty) - Btn2.GetValue(Canvas.LeftProperty) + Btn2.Width);
note first two lines are only in order to have the proportions right in every single movement and resize you do, you can keep it all proportional to the window size.

Getting the top left coordinates of a WPF UIElement

I am working on extending the Microsoft resize Adorner example and need to be able to reposition the element after say the bottom left drag handle has been dragged.
So if I have a textbox of say 150 wide, 35 high postitioned on my form, and the bottom left drag handle changes the width to 200 wide, the right hand of the text box remains unchanged but the left hand edge moves to the left.
So I need to know the top left coordinates of the UIElement. I have tried Canvas.GetLeft and Canvas.GetTop but they return NaN which is confusing.
I just tried VisualTreeHelper.GetOffset which does return an offset but when you try and use it in the arrange method of the element it disappears, presumably as the values in the offset are too high.
In the days before Wpf the coordinate system was quite simple, wpf has overcomplicated things I think.
And if someone just wants the control's screen coordinates:
Point targetLoc = targetCtrl.PointToScreen(new Point(0, 0));
(this doesn't match the thread's description, but it does match the title. Figured it might help people coming in off search results)
You can transform coordinates of the UIElement to its parent. In your case it's a form. Here is an example of a method that returns coordinates of a visual:
private Point GetPosition(Visual element) {
var positionTransform = element.TransformToAncestor(MyForm);
var areaPosition = positionTransform.Transform(new Point(0, 0));
return areaPosition;
}

Categories