I have a grid within a grid and i want the content of the second to move about without encroaching on the first grid.
Much like the panorama view but can move left or right as well as up and down.
I can get this working but unfortunately when you move down the top overflows into the outer grid overlapping any controls within it.
Is there a way to hide the overflow almost like CSS overflow:hidden?
Any help would be really appropriated.
Thank you
Andrew
Possible solution:
var gridWidth = (this.tilesize * (this.gridSize - 1)) / 2;
var top = -(((-offsetY + tileY) * this.tilesize) - gridWidth);
var left = -(((-offsetX + tileX) * this.tilesize) - gridWidth);
this.Container.Margin = new Thickness(left, top, 0, 0);
var clipSection = new RectangleGeometry();
clipSection.Rect = new Rect(-1 * left, -1 * top, 480, 400);
this.Container.Clip = clipSection;
this.Container.Dispatcher.BeginInvoke(new ThreadStart(delegate
{
this.Container.Clip = clipSection;
}));
You could do this by putting something in the cells of the "outer" grid and seeing a higher ZIndex than the elements you are moving around. The elements with the higher ZIndex appear above the lower ones.
Related
I have a UserControl which has a Label at the bottom right corner defined as followed:
this.lblInspectionName.AutoSize = true;
this.lblInspectionName.Font = new System.Drawing.Font("Segoe UI", 10.25F, System.Drawing.FontStyle.Bold);
this.lblInspectionName.Location = new System.Drawing.Point(3, 7);
this.lblInspectionName.Name = "lblInspectionName";
this.lblInspectionName.Size = new System.Drawing.Size(113, 19);
this.lblInspectionName.TabIndex = 0;
this.lblInspectionName.Text = "___";
Its Text content changes based on other events. The problem is that when the Label gets bigger, it goes to left (as I want otherwise it exceeds the right border), but when it gets smaller again the location is the same as the previous case and it's positioned too left.
Do you know how I can let the label grows to left when necessary keeping always a certain distance/margin to the right border? Thanks in advance!
EDIT
Doing as suggested, the situation is the following:
I would add these properties settings
this.lblInspectionName.Dock = DockStyle.Bottom;
this.lblInspectionName.TextAlign = ContentAlignment.BottomRight;
But you need to set the AutoSize back to false.
// Comment out this line. False is default
// this.lblInspectionName.AutoSize = true;
For my Angular JS grid work, I'm using ui-grid rather than ng-grid as ui-grid is meant to be the new version which is purer Angular.
I've got a grid that I'm populating with a http response, and I'm able to select a row (based on finding the record matching a $scope variable value) using the api.selection.selectRow method call.
What I need to do next is scroll the grid to that record.
There's an existing stack overflow question along the same lines that is for ng-grid and the answer to that refers to undocumented features which are not present in ui-grid so I can't use that approach.
The closest I've got is finding $scope.gridApi.grid to get a reference to the actual grid itself but looking through the properties and methods in the Chrome debugger doesn't show anything that sounds like it could work.
You can use the cellNav plugin. You should already have a reference to your row entity from the selection. The documentation is here.
gridApi.cellNav.scrollTo(grid, $scope, rowEntity, null);
I managed to hack together something that works pretty well but it's a bit dodgy and could probably be cleaner with a bit more Angular/jquery understanding.
I used the browser dom explorer to find that the scrollbars have a css class that we can detect to find them and then set the scroll properties on them to have the grid scroll (the grid and scrollbars are separate divs but their properties are bound so changing one updates the other).
It doesn't completely work for scrolling to the last row of the grid. This could be a timing issue, I've noticed when using breakpoints that the grid comes on screen a little larger and then shrinks down to it's final size. This could be messing with the scrolling values.
The first loop finds the height of the grid by adding up the rows, and the y position of the row for my data object (project), then we find the scrollbar and set it's scrollTop, trying to centre the row on screen without going out of bounds.
var grid = $scope.projectsGridApi.grid;
// var row = grid.rowHashMap.get(project.$$hashKey);
var found = false;
var y = 0;
var totalY = 0;
var rowHeight = 0;
for (var rowIdx in grid.rows)
{
var row = grid.rows[rowIdx];
if (row.entity.$$hashKey == project.$$hashKey)
{
found = true;
rowHeight = row.height;
}
if (!found)
{
y += row.height;
}
totalY += row.height;
}
// now find the scroll bar div and set it's scroll-top
// (todo: checking if we're at the end of the list - setting scrollTop > max means it doesn't work properly
var grid = $scope.projectsGridApi.grid;
// annoyingly this is nastily coded to find the scrollbar and isn't completely right
// I think the grid is a little taller when this is called, then shrinks
// which affects what the maximum is (so we might not always be able to put the selected item on screen if it is the last one).
var holderDiv = $('#projectsGridHolder');
if (holderDiv)
{
var scrollBarDivs = holderDiv.find('.ui-grid-native-scrollbar');
if (scrollBarDivs)
{
for (var scrollBarDivIdx in scrollBarDivs)
{
var scrollBarDiv = scrollBarDivs[scrollBarDivIdx];
var scrollBarDivClass = scrollBarDiv.className;
if (scrollBarDivClass)
{
if (scrollBarDivClass.indexOf('vertical') != -1)
{
var scrollHeight = scrollBarDiv.scrollHeight;
var clientHeight = scrollBarDiv.clientHeight;
if (rowHeight > 0)
{
y -= (clientHeight - rowHeight) / 2; // center on screen be scrolling slightly higher up
}
if (y < 0) y = 0;
else if (y > totalY - clientHeight) y = totalY - clientHeight;
scrollBarDiv.scrollTop = y;
}
}
}
}
}
I have a canvas with a background image:
var bi = new BitmapImage(new Uri(imgLocFull));
var ib = new ImageBrush(bi) {Stretch = Stretch.UniformToFill};
MyCanvas.Background = ib;
I am overlaying various shapes on the image, and want the position of the shapes relative to the background image to be fixed.
If my application window is resized, the amount of the image that is cropped, horizontally and vertically, changes, and when my shapes are redrawn, they do not appear in the same position on the background image.
How can I determine how much of the image has been cropped (to apply an adjustment factor to the overlaid objects' positions?) Or is there a better way of fixing the location of a shape relative to the background image?
Here is my present drawing code:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetBottom(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
EDIT: Further Clarification
Here's a concrete example of what I am trying to achieve. My image is an aerial photograph, and I want to mark a particular geographical feature (with, say, an ellipse.)
When the window is resized, the ellipse doesn't stay on the feature, it stays relative to the left and top of the canvas.
I can get it closer to the right place by moving it using a factor (newx = newheight/oldheight * oldx) but this doesn't quite work because of the UniformToFill stretch mode, which sees some of the image clipped off the canvas.
The Top and Left of the Canvas are 'anchored', while the Bottom and Right move when resizing... try setting the Canvas.Top Attached Property instead, along with the Canvas.Left Attached Property as you are:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetTop(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
UPDATE >>>
You asked Or is there a better way of fixing the location of a shape relative to the background image?
I answered this question, so I don't understand why you would need to do anything else... your objects will not move when the screen in resized *if you only set the Grid.Top and Grid.Left properties.
How can I scale PictureBox components to best fit the given space on the screen while keeping their aspect ratio (interdependent of the actual image or its SizeMode) ?
I tested setting the Dock of the FlowLayout and the PictureBox to Fill. I also tested using a Panel as a wrapper and tested different settings for AutoSize and AutoSizeMode.
To give more information about the background: I want to dynamically add and remove images in the viewport of the application, so a TableLayout is in the first step sort of to static. I have to admit I'm was also thinking of calculating the size an position manually - or to dynamically adapt the row and column count of the TableLayout - but it seems to me prone to errors. I thought having a FlowLayout and automatically sized components should be the correct way - but it seems not to work that way. (To speak as web developer, I simply want to "float the images left", "with width and height set to 'auto'" and no scrolling.)
The images should visualize this a bit: the first figure should point out the layout, if there is only one PictureBox - it takes the whole space (or as big as possible with the given aspect ratio). The second shows how I would like the Layout to be, if there are two (three or four) images. The third figure is showing basically a resized window with three (to six) images.
Is there some point I'm missing?
This code snippet do this:
It arranges the visible controls inside a container in respect of the aspect ratio (see R variable in the code), and uses the container margin values to get horizontal and vertical gaps between items. The padding of the container is also handled.
public static void Arrange(Control container)
{
var H = container.DisplayRectangle.Height;
var W = container.DisplayRectangle.Width;
var N = container.Controls.OfType<Control>().Count(c => c.Visible);
var R = 4 / 3d; // item aspect ratio
var margin = container.Margin;
var padding = container.Padding;
var horizontalGap = margin.Left + margin.Right;
var verticalGap = margin.Top + margin.Bottom;
if (N == 0)
return;
var bestSizedItem = (
// Try n rows
Enumerable.Range(1, N).Select(testRowCount =>
{
var testItemHeight = (H - verticalGap * (testRowCount - 1)) / testRowCount;
return new
{
testColCount = (int)Math.Ceiling((double)N / testRowCount),
testRowCount = testRowCount,
testItemHeight = (int)testItemHeight,
testItemWidth = (int)(testItemHeight * R)
};
})
// Try n columns
.Concat(
Enumerable.Range(1, N).Select(testColCount =>
{
var testItemWidth = (W - horizontalGap * (testColCount - 1)) / testColCount;
return new
{
testColCount = testColCount,
testRowCount = (int)Math.Ceiling((double)N / testColCount),
testItemHeight = (int)(testItemWidth / R),
testItemWidth = (int)testItemWidth
};
})))
// Remove when it's too big
.Where(item => item.testItemWidth * item.testColCount + horizontalGap * (item.testColCount - 1) <= W &&
item.testItemHeight * item.testRowCount + verticalGap * (item.testRowCount - 1) <= H)
// Get the biggest area
.OrderBy(item => item.testItemHeight * item.testItemWidth)
.LastOrDefault();
Debug.Assert(bestSizedItem != null);
if (bestSizedItem == null)
return;
int x = container.DisplayRectangle.X;
int y = container.DisplayRectangle.Y;
foreach (var control in container.Controls.OfType<Control>().Where(c => c.Visible))
{
control.SetBounds(x, y,
bestSizedItem.testItemWidth,
bestSizedItem.testItemHeight);
x += bestSizedItem.testItemWidth + horizontalGap;
if (x + bestSizedItem.testItemWidth - horizontalGap > W)
{
x = container.DisplayRectangle.X;
y += bestSizedItem.testItemHeight + verticalGap;
}
}
}
I put this snippet on Gist so you can contribute if you wish.
I'm just creating my own AboutBox and I'm calling it using Window.ShowDialog()
How do I get it to position relative to the main window, i.e. 20px from the top and centered?
You can simply use the Window.Left and Window.Top properties. Read them from your main window and assign the values (plus 20 px or whatever) to the AboutBox before calling the ShowDialog() method.
AboutBox dialog = new AboutBox();
dialog.Top = mainWindow.Top + 20;
To have it centered, you can also simply use the WindowStartupLocation property. Set this to WindowStartupLocation.CenterOwner
AboutBox dialog = new AboutBox();
dialog.Owner = Application.Current.MainWindow; // We must also set the owner for this to work.
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
If you want it to be centered horizontally, but not vertically (i.e. fixed vertical location), you will have to do that in an EventHandler after the AboutBox has been loaded because you will need to calculate the horizontal position depending on the Width of the AboutBox, and this is only known after it has been loaded.
protected override void OnInitialized(...)
{
this.Left = this.Owner.Left + (this.Owner.Width - this.ActualWidth) / 2;
this.Top = this.Owner.Top + 20;
}
gehho.
I would go the manual way, instead of count on WPF to make the calculation for me..
System.Windows.Point positionFromScreen = this.ABC.PointToScreen(new System.Windows.Point(0, 0));
PresentationSource source = PresentationSource.FromVisual(this);
System.Windows.Point targetPoints = source.CompositionTarget.TransformFromDevice.Transform(positionFromScreen);
AboutBox.Top = targetPoints.Y - this.ABC.ActualHeight + 15;
AboutBox.Left = targetPoints.X - 55;
Where ABC is some UIElement within the parent window (could be Owner if you like..) , And could also be the window itself (top left point)..
Good luck