UserControl with autosized form and flowpanel not resizing the height inside a splitpanel - winforms

I'm having some issues trying to adapt my project to use UserControls.
now I have this setup, and the height of my userControl is not auto resizing.
SplitPanel
SplitPanel.panel1
MyUserControl -> autosize true, dock top, achor top left
Form -> autosize true
Button -> dock top
FlowLayout -> dock top, leftToRight, autosize true
some elements: label, dropdown, button
SplitPanel.panel2
other stuffs
Full sized splitPanel
Resized split panel, control not resized
User Control full size
User control resized (flowLayout resized)

So, I found that the Control don't resize itself and I needed to resize myself when the flowPanel resizes:
private void flowLayoutPanel1_Resize(object sender, EventArgs e)
{
var pnl = (FlowLayoutPanel)sender;
pnl.Parent.Size = new Size(pnl.Width, pnl.Height + collapseButtonHeight);
}

Related

C# UserControl Draw outside of TableLayoutPanel cell

C# .Net 4.5 Winform
On my Form, I have a SplitContainer, and in the right panel, my custom UserControl with a TableLayoutPanel.
As I draw UserControl items in each cell of the TableLayoutPanel, I want to use DrawString to display text on the division of the current cell and the cell above it.
Currently:
The cells' UserControls are docked as 'fill' in each cell of the TableLayoutPanel.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
AutoScroll = false;
AutoSize = false;
Dock = DockStyle.Fill;
Margin = new Padding(0);
}
I offset the draw rectangle to be half it's height higher:
var topOffset = ClientRectangle.Top - (ClientRectangle.Height / 2);
paintRect = new Rectangle(ClientRectangle.X + Padding.Left,
topOffset + Padding.Top,
ClientRectangle.Width - Padding.Left - Padding.Right,
ClientRectangle.Height - Padding.Top - Padding.Bottom);
I create a new clipping region for graphics, and print out the text:
using (Graphics newGraphics = this.CreateGraphics())
{
newGraphics.SetClip(paintRect);
e.Graphics.SetClip(newGraphics);
e.Graphics.DrawString(
"ABCD 1234",
Font,
new SolidBrush(ForeColor),
paintRect, style);
}
The text gets cut off - see image
The cell UserControl that needs to display text (at it's top, halfway sticking into the control, and the TableLayoutPanel cell, above it. I think I need to change the clipping of those cells to not clip the text, but am unsuccessful.
How can I display the text 'outside' or 'on top' of the 'layer' that the TableLayoutPanel cell containing the UserControl is in, from within the UserControl OnPaint?

How to select an object in canvas wpf

I am dropping ListBox items (items here are textbox, checkbox, radio buttons when user drops onto canvas we are creating controls dynamic and adding to canvas) to Canvas. Now when user clicks on any item in the canvas, want to show properties on that control.
How to get the selected control from the canvas?
To get UI element under mouse on click you can perform hit testing. In XAML define MouseDown event handler:
<Canvas Mouse.MouseDown="Canvas_MouseDown">
and implement it:
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var canvas = sender as Canvas;
if (canvas == null)
return;
HitTestResult hitTestResult = VisualTreeHelper.HitTest(canvas, e.GetPosition(canvas));
var element = hitTestResult.VisualHit;
// do something with element
}

How to get a one-to-one match of an Adorner with its adorned element within a ScrollViewer?

wpf
I have a control A, (an inkcanvas), within a Grid within a ScrollViewer. Conrol A is taller then the physical window, so the ScrollViewer correctly adds a vertical scroll bar and the entire control can be viewed by scrolling down. When attaching an Adorner with a control B, (another inkcanvas), to control A, scrolling downward shows the Adorner to be cut off at the bottom of the screen. That is, the Adorner is not completely covering the adorned element and/or is not extended downward when scrolling.
How do I get the Adorner (the control) to completely cover the adorned element and respect the ScrollViewer. (I need a one-to-one match between the pixels of the Adorner control and the adorned element within the ScrollViewer).
TIA
Edit#1: The key line in the Adorner that sets the background of the InkCanvas is
_inkcanvas.Background = CreateGrid();
public InkCanvasTextAdorner(InkCanvas element)
: base(element)
{
_element = element;
_visuals = new VisualCollection(this);
_inkcanvas = new InkCanvas();
_inkcanvas.Background = CreateGrid();
_visuals.Add(_inkcanvas);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
adornerLayer.Add(this);
}
If an InkCanvas is used (as the above) the Adorner's background is clipped at the bottom. The adorner control, however, does continue to the bottom of the adorned element.
However, if a Canvas is used instead of the InkCanvas, the Adorner's background does extend to the bottom of the adorned element.
What's wrong?
I'm guessing that the difference in the Background property expanding past the physical screen with the Canvas and not the InkCanvas may be because the Canvas inherits from Panel whereas the InkCanvas does not. Based on the finding that the Canvas background does do what I need, I find the below code does accomplish what I want--the canvas allows images from layers beneath it to be seen yet posts a grid of lines overwhich the InkCanvas will accept strokes. All is well :)
public InkCanvasTextAdorner(InkCanvas element)
: base(element)
{
_element = element;
// The VisualCollection has only one visual parent. I.e. InkCanvasTextAdorner is the parent to the VisualCollection.
// By overriding default rendering behavior of the VisualCollection, any kind of control and its children can be placed in the Adorner.
_visuals = new VisualCollection(this);
_inkcanvas = new InkCanvas();
_inkcanvas.Background = Brushes.Transparent;
_canvas = new Canvas();
_canvas.Background = CreateGrid();
_grid = new Grid();
_grid.Children.Add(_canvas);
_grid.Children.Add(_inkcanvas);
// The _grid is a logical child of the VisualCollection of the Adorner. The ArrangeOverride and MeasureOverride will set up the Grid control.
_visuals.Add(_grid); // Adding a single control for display.
// AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
adornerLayer.Add(this);
}
Which looks like:

Prevent a scrollviewer from refocusing to the left after expanding a child in a treeview

I have a customized TreeView inside a ScrollViewer (I needed to overwrite the template for this application).
The treeviewitems have two columns. One for the togglebutton and the other for the content. The toggle button column width has been set to 0 to hide the toggle button and align all the elements. The items data template contains a canvas that draws a rectangle for each item, which can be quite long in the horizontal, and has a left offset from the canvas.
It all draws correctly but when you double click a rectangle to expand the child, the scrollviewer refocuses the treeview to the left. I assume it is refocusing because it realigns to the toggle button or the left of the item content.
Does anyone have any ideas how to change this behaviour?
Well the suggestion I received from a colleague was to catch the event.
I tried a few different events and found the one that bubbled up to the ScrollViewer.
I caught the MouseDown event on the rectangle, marked it as handled and traversed up the event.Source.Parent until I got to the control to expand the child.
Hope this helps others.
private void GanttBarMouseDown(object sender, MouseButtonEventArgs e)
{
var theVm = ((GanttItemViewModel) ((ContentPresenter) ((FrameworkElement) ((FrameworkElement) e.Source).Parent).TemplatedParent).Content);
if (e.ClickCount == 1)
{
theVm.IsSelected = true;
e.Handled = true;
}
else
{
theVm.IsSelected = true;
theVm.IsExpanded = theVm.IsExpanded ? false : true;
e.Handled = true;
}
}

How do I implement a tab control with vertical tabs in C#?

How do I implement a tab control with vertical tabs in C#?
Create an instance of System.Windows.Forms.TabControl (one of the standard container controls for Windows Forms) and set the Alignment property to Left.
First set in properties the Alignment property to Left.
Second set SizeMode property to Fixe.
Third set ItemSize property to prefered size example width :30 height :120.
After that you need to set the DrawMode property to OwnerDrawFixed.
Next step is define a handler for the DrawItem event of TabControl that renders the text from left to right.
Example
In form Designers.cs file
TabControl.DrawItem += new DrawItemEventHandler(tabControl_DrawItem);
Definition for tabControl_DrawItem method:
private void tabControl_DrawItem(Object sender, System.Windows.Forms.DrawItemEventArgs e)
{
Graphics g = e.Graphics;
Brush _textBrush;
// Get the item from the collection.
TabPage _tabPage = TabControl.TabPages[e.Index];
// Get the real bounds for the tab rectangle.
Rectangle _tabBounds = TabControl.GetTabRect(e.Index);
_textBrush = new System.Drawing.SolidBrush(Color.Black);
// Use our own font.
Font _tabFont = new Font("Arial", (float)12.0, FontStyle.Bold, GraphicsUnit.Pixel);
// Draw string. Center the text.
StringFormat _stringFlags = new StringFormat();
_stringFlags.Alignment = StringAlignment.Center;
_stringFlags.LineAlignment = StringAlignment.Center;
g.DrawString(_tabPage.Text, _tabFont, _textBrush, _tabBounds, new StringFormat(_stringFlags));
}
Effect:Ready horizontal tabcontrol
I was based on https://msdn.microsoft.com/en-us/library/ms404305(v=vs.110).aspx

Resources