How to overlap WPF Images - c#

Is there a way overlap say three images to have them overlap. I am have a case where I bring the top element to the top but it is showing the base layer underneath instead of the second.
Here is what I mean:
Should be this:
The code for it:
// Bottom Box
this.BottomBox.BackColor = Color.Transparent;
this.BottomBox.BackgroundImage = Resource.BottomBox;
this.BottomBox.Name = "BottomBox";
// Middle Box
this.Middle.BackColor = Color.Transparent;
this.Middle.BackgroundImage = Resource.MiddleBox;
this.Middle.Parent = BottomBox;
this.Middle.Name = "Middle";
// Top Box
this.TopBox.BackkColor = Color.Transparent;
this.TopBox.BackgroundImage = Resource.TopBox;
this.TopBox.Parent = MiddleBox;
this.TopBox.Name = "TopBox";

The easiest way to overlap controls/views (images, etc) in WPF is to put them inside a Canvas or a Grid...
In a Canvas, you can alter there relative positions using the attached properties Canvas.Top and Canvas.Left.
In a Grid, you can alter their relative positions using margins...
You can do this in the Constructor of the views immediately below the InitializeComponent method.
Sample Code:
// Bottom Box
this.BottomBox.BackColor = Color.Transparent;
this.BottomBox.BackgroundImage = Resource.BottomBox;
this.BottomBox.Name = "BottomBox";
// Middle Box
this.Middle.BackColor = Color.Transparent;
this.Middle.BackgroundImage = Resource.MiddleBox;
this.Middle.Parent = BottomBox;
this.Middle.Name = "Middle";
// Top Box
this.TopBox.BackkColor = Color.Transparent;
this.TopBox.BackgroundImage = Resource.TopBox;
this.TopBox.Parent = MiddleBox;
this.TopBox.Name = "TopBox";
var canvas = new Canvas();
canvas.Children.Add(this.BottomBox);
canvas.Children.Add(this.TopBox);
canvas.Children.Add(this.Middle);
Canvas.SetLeft(this.BottomBox, 50);
Canvas.SetTop(this.BottomBox, 100);
Canvas.SetLeft(this.Middle, 50);
Canvas.SetTop(this.Middle, 50);
Canvas.SetLeft(this.TopBox, 50);
Canvas.SetTop(this.TopBox, 0);
//put canvas as the main element to display in the view
Try it out and leave a comment if you have any further issue.

Related

Print multiple canvas WPF?

Today I'm working with WPF! My app is almost finished, except for the last feature. I have created a graphic element which represents a label like the ones you can see under the goods in a supermarket shelf. Print one of them is easy, using PrintDialog.PrintVisual(myVisualItem,"description");.
Now, I have to print a series of these labels, using PintVisual() in a loop, prints every element in a separate document! There's no overload of PrintVisual() which accepts an IEnumerable of visual item. I've seen online that i should paginate these elements, but I cannot find a way to do it What can I do? Thanks!
You could combine all canvas you got into one big canvas and then print this one.
Here is some sample code how to concat multiple canvas into one big one:
public Canvas CombineCanvases(params Canvas[] canvases)
{
// Force each canvas to update its desired size
foreach (var canvas in canvases) { canvas.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); }
var result = new Canvas
{
Height = canvases.Sum(x => x.DesiredSize.Height), // add all heights to get needed height
Width = canvases.Max(x => x.DesiredSize.Width) // find required width
};
var pos = 0d;
foreach (var canvas in canvases)
{
Canvas.SetLeft(canvas, 0);
Canvas.SetTop(canvas, pos); // position element at this pixel count
pos += canvas.DesiredSize.Height; // and increment it
result.Children.Add(canvas);
}
return result;
}
You need to pass all canvas's you want to print and print the result.
var c1 = new Canvas
{
Width = 100,
Height = 100,
Children = { new TextBlock { Text = "Canvas 1" } }
};
var c2 = new Canvas
{
Width = 100,
Height = 100,
Children = { new TextBlock { Text = "Canvas 2" } }
};
var canvas = CombineCanvases(c1, c2);
// print canvas here
Pagination would be if you check how many labels fit on one page and then not concat all canvas into one huge on, but just take as many as are needed to fill one page.
Then print the page and repeat this until all Labels were printed. This is called pagination.
If you believe they will all fit on one page, you could put them in a StackPanel with Orientation = Vertical. Then print the stack panel.
var panel = new StackPanel() { Orientation = Orientation.Vertical };
panel.Children.Add(canvas1);
panel.Children.Add(canvas2);
panel.UpdateLayout();
var dlg = new PrintDialog();
dlg.PrintVisual(panel, "description");

How to add right border of grid in Chart contol

Here is my code for setting properties of chart which is attached above:
chart2.ChartAreas[0].CursorX.IsUserEnabled = true;
chart2.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
chart2.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart2.ChartAreas[0].AxisX.Title = "t";
chart2.ChartAreas[0].AxisY.Title = "w(t)";
chart2.ChartAreas[0].AxisX.Minimum = classes[0].First();
chart2.ChartAreas[0].AxisX.Maximum = classes[m - 1].Last();
chart2.ChartAreas[0].AxisX.Interval = delta_t;
chart2.ChartAreas[0].AxisX.LabelStyle.Format = "{0:0.####}";
I need to add right border of grid so that it will be as it is shown below:
The right border is missing since your data don't nicely fit into the area.
There are many ways to fix this.
Here is the simplest one:
chart2.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart2.ChartAreas[0].AxisY2.LabelStyle.Enabled = false;
This adds a secondary Y-Axis and turns off its labels.
You can style it as needed:
chart2.ChartAreas[0].AxisY2.MajorTickMark.Enabled = false;
chart2.ChartAreas[0].AxisY2.LineWidth = 3;
You could also draw a line or add an annotation but this is by far the easiest solution.

Xamarin forms location of Grid or Button on screen

I have been trying for a while to find the exact location of a grid and the button inside the grid I have on my screen. It is within many layers of Grids and StackLayouts, which have varying paddings.
I have tried using absolute layout, but it never puts the control i'm trying to draw over it in the correct place.
Grid g = new Grid;
g.BackGroundColor = Color.Pink;
g.WidthRequest = 48;
g.HeightRequest = 48;
g.VerticalOptions = LayoutOptions.Start;
g.HorizontalOptions= LayoutOptions.Start;
g.TranslationX = AbsoluteLayout.GetLayoutBounds(LeftButton).Location.X;
g.TranslationY = AbsoluteLayout.GetLayoutBounds(LeftButton).Location.Y;
PageSizedGrid.Children.Add(g);

Button image sides cropped

I'm trying to fit image to button perfectly.
But the image is cropped on its right and bottom faces, see attached print screen:
I edited the button as follows:
var l_oStopImage = Image.FromFile(#"C:\Users\AmitL\Downloads\Button-2-stop-icon72p.png");
var l_oStopPic = new Bitmap(l_oStopImage , new Size(btnStopOperation.Width, btnStopOperation.Height));
btnStopOperation.Image = l_oStopPic ;
btnStopOperation.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
btnStopOperation.TabStop = false;
btnStopOperation.FlatStyle = FlatStyle.Flat;
btnStopOperation.FlatAppearance.BorderSize = 0;
I also tried to edit the BackgroundImageLayout but none of the ImageLayouts fixed the problem..
Any suggestions?
Thanks in advance
1https://msdn.microsoft.com/en-us/library/system.windows.forms.imagelayout(v=vs.110).aspx
You should use stretch, I suggest in designtime (this is not java where you have to add elements by code):
this.buttonOk.BackColor = System.Drawing.SystemColors.MenuHighlight;
this.buttonOk.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("buttonOk.BackgroundImage")));
this.buttonOk.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonOk.Location = new System.Drawing.Point(475, 15);
this.buttonOk.Name = "buttonOk";
this.buttonOk.Size = new System.Drawing.Size(50, 50);
this.buttonOk.TabIndex = 11;
this.buttonOk.UseVisualStyleBackColor = false;
this.buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
And it will work, done it many times before
I got this code from my own working Form1.Designer.cs but because of that: please use the Visual Studio designer and don't try to write all this code / logic in your constructor or something.
The problem is because you are showing an image with the same size as your button.
When you want an image fit in your button, the width and height of image should be at least 1 point less than your button size. (or in other word, you can set your button width and height 1 point more than the image size).
So you can change your code to this:
var l_oStopPic = new Bitmap(l_oStopImage ,
new Size(btnStopOperation.Width-1, btnStopOperation.Height-1));

Make two form controls resize with window evenly

I have a form that looks like this in designer, two grid views, exactly the same properties. It worked for a bit, but now when I resize it, only the right grid view expands horizontally, they both expand vertically. Also locking the form and controls doesn't stop me from resizing the Form which would be easiest solution.
What could cause this? The only relevant properties on the Grid Views are anchors for Top, Right, Left, Bottom on each. See code at bottom.
Here are some screenshots:
Here is the form in Designer:
And here is the form when I try to resize it:
As you can see the right half is wider, I also cannot resize it normally, as I try a diagonal resize it mainly grows vertically, a horizontal resize does the same thing. I've had the resizing issue forever, but the two gridviews were both resizing equally at first, I made no changes and they stopped. Am I missing something here? Why doesn't locking the form stop it from being resizable? I locked every control as well.
Just in case, here is the code for the grid views in the designer, first the right one:
// clientHistoryTableDataGridView
//
this.clientHistoryTableDataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.clientHistoryTableDataGridView.AutoGenerateColumns = false;
this.clientHistoryTableDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
this.clientHistoryTableDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
this.clientHistoryTableDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.clientHistoryTableDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn4,
this.dataGridViewTextBoxColumn5,
this.dataGridViewTextBoxColumn6});
this.clientHistoryTableDataGridView.DataSource = this.clientHistoryTableBindingSource;
this.clientHistoryTableDataGridView.Location = new System.Drawing.Point(426, 52);
this.clientHistoryTableDataGridView.Name = "clientHistoryTableDataGridView";
this.clientHistoryTableDataGridView.RowHeadersVisible = false;
this.clientHistoryTableDataGridView.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.clientHistoryTableDataGridView.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.clientHistoryTableDataGridView.Size = new System.Drawing.Size(430, 360);
this.clientHistoryTableDataGridView.TabIndex = 4;
this.clientHistoryTableDataGridView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.clientHistoryTableDataGridView_CellContentClick);
and the left side:
// clientTableDataGridView
//
this.clientTableDataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.clientTableDataGridView.AutoGenerateColumns = false;
this.clientTableDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
this.clientTableDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
this.clientTableDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.clientTableDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3});
this.clientTableDataGridView.DataSource = this.clientTableBindingSource;
this.clientTableDataGridView.Location = new System.Drawing.Point(1, 52);
this.clientTableDataGridView.Name = "clientTableDataGridView";
this.clientTableDataGridView.RowHeadersVisible = false;
this.clientTableDataGridView.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.clientTableDataGridView.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.clientTableDataGridView.Size = new System.Drawing.Size(428, 360);
this.clientTableDataGridView.TabIndex = 3;
this.clientTableDataGridView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.clientTableDataGridView_CellContentClick);
EDIT:
I fixed the resizing issues by using both answers together. And also disabling autosize on the main form and setting borderstyle to sizable.
possible solution:
add SplitContainer with anchor Left|Top|Right|Bottom
set SplitterDistance at half of SplitContainer width
put clientTableDataGridView in left panel and set Dock = Fill
put clientHistoryTableDataGridView in right panel and set Dock = Fill
You can resolve this problem in the following manner:
Set anchors for both gridview as Top | Bottom.
Override OnResize method of your form and in this method set width and location if both gridviews manually like this:
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
var width = ClientRectangle.Width / 2;
clientTableDataGridView.Left = 0;
clientTableDataGridView.Width = width;
clientHistoryTableDataGridView.Left = width;
clientHistoryTableDataGridView.Width = width;
}
And of course, instead of setting anchors in step 1 - you can completly manage gridviews size in OnResize. Here I've mentioned that step just for simplicity.

Categories