C# WinForms numericUpDown control (removing the spin box) - c#

After a ton of googling, I couldn't come up with anything..
Is there any way to get a numericUpDown control that does not have the spin box?
I need a textbox that only accepts integers, and a numericUpDown has the perfect behavior that I am looking for. However, I need to hide the numeric spinbox for space constraints.
When I try to do something like numericUpDown.Controls[0].Hide() or numericUpDown.Controls.RemoveAt(0), the spinbox disappears but leaves an unusuable void where the spinbox used to be. Thus the numbers scroll at that point, meaning the space is wasted..
Is there any other solution to this?
Thanks..

You can inherit from NumericUpDown. The trick is to hide control when the control is created.
public class NumericUpDownWitoutButtons : NumericUpDown
{
public NumericUpDownWitoutButtons()
{
Controls[0].Visible = false;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(SystemColors.Window);
base.OnPaint(e);
}
}
If the place were buttons should be looks weird, override OnPaint too.
Also, you probably don't need NumericUpDown. Would it be enough to validate that only digits can by typed in? C# Numbers Only Textbox

I settled for disabling the arrow buttons, as less ugly than trying to hide or remove them.
Immediately after this boilerplate code:
internal MainWin()
{
InitializeComponent();
, add this:
myNumericUpDown.Controls[0].Enabled = false; // Disable the arrow buttons.
Also: set InterceptArrowKeys to false in the control's properties, to prevent arrow keys (on the keyboard) from incrementing and decrementing myNumericUpDown.Value.
Bad ways:
myNumericUpDown.Controls[0].Hide(); // Hide the arrow buttons.
// This leaves a gray patch that turns white after minimize-and-restore.
myNumericUpDown.Controls.RemoveAt(0); // Remove the arrow buttons.
// This leaves a gray patch that turns white after minimize-and-restore.
Half-bad way:
Forget the above. Only set Increment to 0 in the control's properties. The arrow buttons still operate, and the arrow keys (on the keyboard) are still intercepted, but now they do nothing. Sadly, no-action buttons are probably less intuitive than disabled arrow buttons. (I'm surprised that it even accepts Increment = 0. A smart version of this control would neatly hide the arrow buttons when the increment is 0.)
Other solution(s):
A number-box can be implemented as a TextBox with extra code that restricts input to only numbers, and returns or announces a numeric value (decimal or your choice). (Searching finds many diverse, complex examples.) Pasted data comes in differently from keystrokes, so additional code is needed to handle pastes. (Upside: You can make the number-box smarter than the built-in NumericUpDown: NumericUpDown stupidly accepts and displays . until the user presses Enter or leaves the field, even if you specify DecimalPlaces = 0; and it accepts and displays multiple decimal points, which is nonsense.)
An integer-box is simpler than a generalized number-box that accepts real numbers (optionally in floating-point notation) and returns a real-number type (float, double, or decimal).

Related

How to make a Windows Form responsive [duplicate]

I have read several stack overflow questions without finding a good working solution to my problem. How can I resize my controls whenever the form is resized? I would like them to get larger or smaller when the form becomes larger or smaller.
In visual basic this was quite easy to do with the form.Zoom property (which did't really require resizing controls of course, but solved what I needed). Unfortunately this is not available in C# winforms.
Here is some other things I have tried without luck:
private void formMain_Resize(object sender, EventArgs e)
{/*
double scale;
this.scaleWidth = (float)this.Width / (float)this.origWidth;
this.scaleHeight = (float)this.Height / (float)this.origHeight;
if (this.scaleHeight > this.scaleWidth)
{
scale = this.scaleHeight;
}
else
{
scale = this.scaleWidth;
}
foreach (Control control in this.Controls)
{
control.Height = (int)(control.Height * this.scaleHeight);
control.Width = (int)(control.Width * this.scaleWidth);
this.Refresh();
// control.Font = new Font("Verdana", control.Font.SizeInPoints * heightRatio * widthRatio);
}
///////This scaling didnt work for me either
//this.Scale(new SizeF(this.scaleWidth, this.scaleHeight));
//this.Refresh();
*/
}
If I overlooked an actualy working sample of code on another stack overflow question I would love to see it, but the ones I found were similar to those above which are not working.
Perhaps I was misusing it and someone could post sample code to show for those of us who keep asking this question how to go about solving the problem.
Also, I have tried using some of the anchor/docking tools thinking they would automatically allow it but it didn't.
The best option is to use a TableLayoutPanel. Put TableLayoutPanel on the form, set the Dock property to Fill, create required rows and columns and put the controls inside the cells. Of course you need to set Dock/Anchor on the controls inside the cells, so they respond to changes to the cell size. In some situations you may need to put a Panel into a cell and drop the controls inside it, because every cell can only contain a single control. You may also need to set RowSpan/ColumnSpan on the controls.
By using a TableLayoutPanel, you have complete control over how your cotrols should be arranged. You can set absolute or percentage size for rows and columns.
Use Anchor of the control. There's an option on anchoring the top, bottom, left and right. And you're good to go.
I found an alternative solution that is working well for me, appreciate any negative or positive comments on the solution.
Using several Split Containers and Split Containers inside of Split Containers in different regions I am able to section off the primary pieces of the layout, and within there utilizing Docking and Anchoring I am able to accomplish exactly what I wanted to do - it works beautifully.
I would point out I am aware that some folks online mention split containers use lots of resources.
If your controls are in a group box, be sure to set the group boxes properties to resize. Controls inside the box are controlled by the box. The box size (unless it is inside another box) is controlled by the form.
What you are trying to do in your code is to change the sizes of the controls which isn't so good approach. Generally, the size of the Buttons and TextBoxes shouldn't be changed when you re-size your form, but they often need to move (change location). Some controls do need to change size according to the re-sized form and but in most cases only one dimension. The central controls that are used for working area (if you are developing the tool for drawing for instance) should change sizes of both dimensions. All this you can accomplish by properly setting Dock and/or Anchor properties of the controls.
textBox1.Dock = DockStyle.Bottom;
textBox1.Anchor = AnchorStyles.Bottom & AnchorStyles.Left;
All these are also easily set in the Properties panel when using designer.
But if that isn't enough for you, in rare cases, you will most definitely want to only change the location of the control:
textBox1.Location = new Point(newX, newY);

DataTemplateSelector disappearing data on save mystery

I'm not even sure what to call it so let me explain the scenario and hopefully a light bulb goes off for somebody else. I can't do a full code share to reproduce because it just isn't an option, anyhow I digress.
So, here's the basics.
Multiple DataTemplate's set via;
public DataTemplate ABCTemplate
{
get { return (DataTemplate) GetValue(ABCTemplateProperty); }
set { SetValue(ABCTemplateTemplateProperty, value); }
}
Which are swapped out via;
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var something = (thestuff)item;
switch (something.Id)
{
case (int)thestuff.Type.ABC: { return ABCTemplate; }
case (int)thestuff.Type.DEF: { return DEFTemplate; }
case (int)thestuff.Type.GHI: { return GHITemplate; }
case (int)thestuff.Type.JKL: { return JKLTemplate; }
}
return base.SelectTemplate(item, container);
}
etc, etc, etc. Each DataTemplate is a DataGrid (no I did not make this and I can't rewrite it).
Here's the weird mystery part that has me stumped that I'll explain best I can.
On initial load of the screen everything is fine, the data loads fine, everything is peachy. HOWEVER upon Save (even without any changes) once the busy indicator disposes then ONLY the Column Headers of the DataGrids will remain visible UNTIL you resize the screen even the slightest bit. Which I assume causes SizeChanged to UpdateLayout()?
My question is, has anyone seen this behavior before? Why the hell would the DataGrid of each template render the Column Headers, but then NOT render the rows until just a SizeChanged event, and most importantly, how can I fix this P.O.S.?
I tried the first stuff I could think of like just hard setting some sizes since I took a shot in the dark on the fact that changing the window size even the slightest bit causes the data to return to view but in reality, I'm stumped and doing that just made it less predictably reproducible.
I'll happily buy beer for anyone that can save my sanity. Thanks.
This actually does ring a bell. I had to fight a similar DataGrid rendering issue. Here is my story:
The content disappeared or was completely white when we added columns, after a while I found out it happened when the combined width of all columns exceeded a certain number. I don't think it was Int32.MaxValue, it was probably a smaller number, maybe it was a power of two, but that is not important or required. (see my explanation further down)
So your save operation's busy indicator might effect the visualState in any way, some kind of focus border or stuff might be rendered and just hits this magical limit, an overflow will happen.
Now imagine some code that for example calculates the width of a contentPanel or Presenter (or anything related to showing your content) sums up all the parts, and an overflow happens, what will be the result? yeah, exactly, the width will be far in the negative. So it actually might be rendered by the engine, either off screen or just outside of the element's actual display area.
You can actually reproduce this and witness it with a TextBox in a try-out project: Have a TextBox and fill it with random characters via Ctrl+A, Ctrl+C, Ctrl+V, and onTextChanged -> Debug.WriteLine(textbox.Text.GetRenderedWidth()).
(GetRenderedWidth is an extension method I wrote, can give you the code if you want. But it is not super accurate.)
As soon as the rendered width reaches ca. 39,235 you can see a change in the rendering of the Ctrl+A text highlighter: The content is gone! But actually it is just rendered into negative direction (you can turn on EnableRedrawRegions to see it rendered in the wrong direction). and everything is back to normal when you remove the last character again.
So my advise is: turn on EnableRedrawRegions, see if you can see a change of the redrawn regions when your rendering issue occurrs. If you can spot a region is drawn just left of you DataGrid, chances are that that is actually your grid content.
[Edit 1]
If it turns out that the visualState change of the grid is somehow causing this bug, your fix might be as simple as onBusyIndicatorDone -> VisualStateManager.GoToState(grid,"normal",false);
[Edit 2]
You can trigger a redraw with InvalidateArrange or InvalidateMeasure: grid.InvalidateArrange() or grid.InvalidateMeasure()

Is it possible to get which character of text is clicked on C# form?

I am trying to get which of the * is clicked in text of label as in picture.
NOTE : Number of * is not known at first.User inputs it.So the position of mouse click is not useful.
Answer is :
X of first *'s location is known, equals = 10 .The asterisks are spaced equally,distance between two * is ~15 pixel .
When user clicks on one of asterisks , index of asterisks can be calculated as the code below
private void label4_MouseDoubleClick(object sender, MouseEventArgs e)
{
double t = (e.X - 10) / 15.0;
int indexOfClickedAsterisk=(int)Math.Round(t) + 1;
}
It depends. If you are willing to display the text in a TextBox instead of Label (which is what it looks like you're using now), then you can use the GetCharIndexFromPosition method. Just make sure you specify the Point in client coordinates (comes for free if you are handling mouse clicks in the Label control itself).
Note that you can set the TextBox as ReadOnly, assuming you don't want the user actually modifying the text. They will still be able to select the text though.
If you need an actual Label control (e.g. you don't even want selectable text and the grayed-out appearance of a disabled TextBox isn't appropriate), then you'll have to write your own (or find one online that someone else wrote already), as the built-in one doesn't have that functionality. It would not be too difficult. You can use the TextRenderer methods to determine where each character is laid out when drawn and then use that information to correlate character positions with mouse clicks.

Windows Phone: View shifts up when textbox gets focus

WP8 : Whenever a texbox comes into focus, the corresponding view of the page shifts up by a margin. Due to which the heading of the page gets cut. I have found a solution to this problem here , but it doesn't help. Does not work on WP8. Any solutions are appreciated.
You can disable that shift by changing RenderTransform back to zero:
private void TextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
App.RootFrame.RenderTransform = new TranslateTransform();
}
First you can disable shift using the RenderTransform back to zero as #Ku6opr mentioned. But the real question is would it really do what you want. Noone likes to type if I can not see what I'm typing, this is the reason behind shifting the view upward.
If you really want to prevent shifting redesigning the view for a smaller space will be a much better option. Only disabling the shift somehow wouldn't help much.

Resize Controls with Form Resize

I have read several stack overflow questions without finding a good working solution to my problem. How can I resize my controls whenever the form is resized? I would like them to get larger or smaller when the form becomes larger or smaller.
In visual basic this was quite easy to do with the form.Zoom property (which did't really require resizing controls of course, but solved what I needed). Unfortunately this is not available in C# winforms.
Here is some other things I have tried without luck:
private void formMain_Resize(object sender, EventArgs e)
{/*
double scale;
this.scaleWidth = (float)this.Width / (float)this.origWidth;
this.scaleHeight = (float)this.Height / (float)this.origHeight;
if (this.scaleHeight > this.scaleWidth)
{
scale = this.scaleHeight;
}
else
{
scale = this.scaleWidth;
}
foreach (Control control in this.Controls)
{
control.Height = (int)(control.Height * this.scaleHeight);
control.Width = (int)(control.Width * this.scaleWidth);
this.Refresh();
// control.Font = new Font("Verdana", control.Font.SizeInPoints * heightRatio * widthRatio);
}
///////This scaling didnt work for me either
//this.Scale(new SizeF(this.scaleWidth, this.scaleHeight));
//this.Refresh();
*/
}
If I overlooked an actualy working sample of code on another stack overflow question I would love to see it, but the ones I found were similar to those above which are not working.
Perhaps I was misusing it and someone could post sample code to show for those of us who keep asking this question how to go about solving the problem.
Also, I have tried using some of the anchor/docking tools thinking they would automatically allow it but it didn't.
The best option is to use a TableLayoutPanel. Put TableLayoutPanel on the form, set the Dock property to Fill, create required rows and columns and put the controls inside the cells. Of course you need to set Dock/Anchor on the controls inside the cells, so they respond to changes to the cell size. In some situations you may need to put a Panel into a cell and drop the controls inside it, because every cell can only contain a single control. You may also need to set RowSpan/ColumnSpan on the controls.
By using a TableLayoutPanel, you have complete control over how your cotrols should be arranged. You can set absolute or percentage size for rows and columns.
Use Anchor of the control. There's an option on anchoring the top, bottom, left and right. And you're good to go.
I found an alternative solution that is working well for me, appreciate any negative or positive comments on the solution.
Using several Split Containers and Split Containers inside of Split Containers in different regions I am able to section off the primary pieces of the layout, and within there utilizing Docking and Anchoring I am able to accomplish exactly what I wanted to do - it works beautifully.
I would point out I am aware that some folks online mention split containers use lots of resources.
If your controls are in a group box, be sure to set the group boxes properties to resize. Controls inside the box are controlled by the box. The box size (unless it is inside another box) is controlled by the form.
What you are trying to do in your code is to change the sizes of the controls which isn't so good approach. Generally, the size of the Buttons and TextBoxes shouldn't be changed when you re-size your form, but they often need to move (change location). Some controls do need to change size according to the re-sized form and but in most cases only one dimension. The central controls that are used for working area (if you are developing the tool for drawing for instance) should change sizes of both dimensions. All this you can accomplish by properly setting Dock and/or Anchor properties of the controls.
textBox1.Dock = DockStyle.Bottom;
textBox1.Anchor = AnchorStyles.Bottom & AnchorStyles.Left;
All these are also easily set in the Properties panel when using designer.
But if that isn't enough for you, in rare cases, you will most definitely want to only change the location of the control:
textBox1.Location = new Point(newX, newY);

Categories

Resources