I'm using a Popup to show validation messages to the User. If the element (e.g. a Textbox) is scrolled out of the View the following Method is working great and i can easy hide the Popup.
Determine control is Visible
But if i move the window partial out of the screen so i can't see the element anymore this Method still returns true. In this case the popup is still visibile to the User (The popup allways stays within screen bounds) but the element is not.
How can i check if a element is visibile within the screen?
This can be done using PrimaryScreenWidth and PrimaryScreenHeight available in SystemParameters. You need to calculate the position of control relative to screen and check whether that point exist in screen bounds.
Point locationFromWindow = this.textBox.TransformToVisual(this).Transform(new Point(0, 0));
Point point = this.textBox.PointToScreen(new Point(0, 0));
Rect rect = new Rect(0, 0, SystemParameters.PrimaryScreenWidth, SystemParameters.PrimaryScreenHeight);
if (!rect.Contains(point))
{
// Outside screen bounds.
}
Related
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
}
}
I'm working on a WPF project where I have a grid of thumbnails (each thumbnail is a SurfaceButton), and clicking on each thumbnail shows its own popup menu. The popup menu in each case has its 'sibling' photo thumbnail as its placement target. The thumbnail and popup sit alongside each other in a Grid.
I've designed the popup to emulate the kind of popout scrollable menu that you'd find in iOS, complete with a little triangle arrow that points up to the thumbnail the popup relates to (with the popup appearing below the thumbnail).
But, much to my pleasant surprise, if you click on a thumbnail that's at the bottom of the screen, WPF moves the popup above the thumbnail so that it's not off-screen.
This is great, but how can I compare the positions of the two elements and move the arrow accordingly (or hide it and show another), so that the popup above the thumbnail is pointing down to it?
Hope that makes some sense!
I've tried VisualTreeHelper.GetOffset, but that only returns the offset from the element's parent, and these seem to always be 0,0 or 1,1. I've also tried UIElement.PointToScreen, but the numbers I get back from the two elements don't seem to vary when the popup moves.
I'm sure there's a simple solution that I'm missing.
You can get your popup's actual placement like below
// ComboBox for example:
Popup popup = yourcombobox.Template.FindName("PART_Popup", yourcombobox) as Popup;
popup.Opened += (s, a) => {
// structure inside will be different by your templates
Dacorator decorator = (s as popup).Child as Decorator;
Border border = decorator.Child as Border;
Double y0 = yourcombobox.PointToScreen(new Point(0,0)).Y;
Double y1 = border.PointToScreen(new Point(0,0)).Y;
if(y0 > y1) {
// when shows at the top
yourcombobox.Background = Brushes.Red;
} else {
// when shows at the botttom
yourcombobox.Background = Brushes.Blue;
}
};
Popup doesn't have it's own size or position, so you have to catch the child's position only when popup is shown.
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/popup-overview
Another problem in my WPF questions series :)
I'm creating custom Decorator that will be used to decorate Panels (or it can be Behavior, no difference).
That Decorator deals with elements that are in that Panel (Children property of the Panel). It attaches some RenderTransforms to those elements. Now I need a position of some element ('child' of the Panel) relative to the Panel itself. In other words I need a position if some child element in the Panels coordinate space. in just another words I want the offset that was specified by the ArrangeOverride method of the Panel when calling Arrange method on Children.
That seem to be easy. But I cannot find the way to always get right coordinates.
This code
VisualTreeHelper.GetOffset(child)
does not work when the panel is inside ScrollView - it takes topmost, leftmost visible corner of the Panel as an origin of coordinate space - not the real topmost and leftmost corner of the Panel.
The code
Point position = child.TransformToAncestor(panel).Transform(new Point(0,0));
will not work when some render transforms are already active on the child element of the Panel. It will return the position of transformed image(by the render transfrom) of child element. The render position.
The same problem is with this aproach:
Point panelPosition = panel.PointToScreen(new Point(0, 0));
Point childPosition = child.PointToScreen(new Point(0, 0));
Point position = new Point(childPosition.X - panelPosition.X, childsPosition.Y - panelPosition.Y);
So this i what I have tryied but it did not work. I have 2 similar questions on this topic that were tying to simplify the problem, so I got some of suggestions above. Now I introduced the problem in its full complexity, I hope to get the right advice.
If something is unclear please leave the comment.
Thank you
You can "undo" the RenderTransform before calling TransformToAncestor:
Point origin = child.RenderTransform.Inverse.Transform(new Point(0, 0));
Point position = child.TransformToAncestor(listBox).Transform(origin);
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;
}
I use the function PointToScreen to get the screen related point of the control it gives proper value if I use this function for the toolstrip which is top on the form, but if there is menustrip on the top of the form and then under the menustrip, toolstrip is there then the function does not give proper value of screen point for the control toolstrip.
So,when I use this function for the toolstrip which is top on the form right now then it gives proper location like it gives Y position of 26 which is ok.
Now I am adding the menustrip top of the form and toolstrip is now under the menustrip and now if I use the function then it does not give proper value like,it gives y position of 74,which should be (26 + height of menustrip) = 50.
I would verify that you are calling PointToScreen on the correct control. If you want to find the location of a control in screen coordinates, call PointToScreen on its parent control.
For example:
control.Parent.PointToScreen(control.Location);
If you call PointToScreen on the control itself using a point relative to the parent control (such as Control.Location), you will get the wrong location.
For example:
Lets say control.Location = new Point(0, 20). If the parent is located at (100, 100) relative to the desktop, then the desktop position of the control is (100, 120). If you call PointToScreen on the parent control, then you will get (100, 120). If you call PointToScreen on the control itself, you will get the location of the point (0, 20) relative to the desktop location of the control, which would end up being (100, 140).