DatePicker no Characters allowed - wpf

Short Question, is it possible to disable Characters Entry in a DataPicker so that the User is just allowed to enter numbers and dots and slashes?
Kind Regards

You could handle the PreviewTextInput event of the DatePicker something like this:
<DatePicker x:Name="dp" PreviewTextInput="DatePicker_TextChanged" />
Private Sub DatePicker_TextChanged(sender As Object, e As TextCompositionEventArgs)
If Not (Microsoft.VisualBasic.Information.IsNumeric(e.Text) Or e.Text = "." Or e.Text = "/" Or e.Text = "\") Then
e.Handled = True
End If
End Sub
Is there anyway to do this in Code behind?
Sure. Try this:
AddHandler dp.PreviewTextInput, AddressOf DatePicker_TextChanged

You're going to have to do it yourself :
<TextBox PreviewTextInput="TextBox_PreviewTextInput"/>
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if(!is_number(e.Text) && !is_dot(e.Text) && ...)
{
e.Handled = true;
}
}
Setting e.Handled = true intercepts the event and prevents the action to take place.
I would recommend using a regex instead of is_number etc... (I'm sure there are plenty of examples of regexes out there).
Note that this will not work with spacebar, you will have to use the previewkeydown event for that, and there might be some other keys that are not treated in PreviewTextInput and that would modify your Text, but I can not think of any.
EDIT :
I just saw you use VB, the code I posted is for C#, I don't know any VB but I imagine it shouldn't be that different.

Related

WPF send key to textBox

I'm working on a virtual keyboard, but i struggle to send Keys. Nothing happens, except when i hard-add them to the textbox. Here's my code
public static void Send(Key key)
{ //Found online
var e = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key)
{
RoutedEvent = Keyboard.KeyDownEvent
};
InputManager.Current.ProcessInput(e);
}
private void ClickOnKey(object sender, RoutedEventArgs e)
{
CustomButton cb = sender as CustomButton;
string text = cb.text;
Console.WriteLine(text);
element_to_focus.Focus(); //The textbox
Send(translate_string_to_key(text));
}
ProcessInput seems to only raise the appropriate key-related events, but will not actually modify the text.
If you really want to simulate key presses, you'll need to leverage p/invoke and use SendInput. Luckily, someone's already done the p/invoke work for us and has made their work available:
https://archive.codeplex.com/?p=inputsimulator
It's also available as a NuGet package (I found two versions):
https://www.nuget.org/packages/InputSimulator/
https://www.nuget.org/packages/InputSimulatorPlus/

How do I use the Trim Function

I'm converting a web project from VB to C#, and I can't figure out how to implement the trim function. Do I have to write a specific function, or is there a way to use it in the context of my project? Here is the functional VB code I'm trying to convert. If you need more details, please ask.
Protected Sub ButtonSetup(ByVal Dr As DataRow, ByVal Btn As Button)
Btn.Visible = True
Btn.Text = Dr("Floor_Name").ToString.Trim()
Btn.CommandArgument = Dr("Floor_File").ToString.Trim()
Btn.CssClass = "GreyButtonStyle"
AddHandler Btn.Click, AddressOf Me.Schematic_Button_Click
End Sub
Indexer
C# uses the square bracket[] to access element of an indexer instead of parentheses()
Event Handler
AddHandler and AddressOf are both VB keyword. In order to add an handler to an event, use the += operator with the event as left operand and handler as the right operand.
protected void ButtonSetup(DataRow row, Button button)
{
button.Visible = true;
button.Text = row["Floor_Name"].ToString().Trim();
button.CommandArgument = row["Floor_Name"].ToString().Trim();
button.CssClass = "GreyButtonStyle";
button.Click += Schematic_Button_Click;
}
I work in C# and your code is VB, but it looks like you are just calling it wrong.
You have
Btn.Text = Dr("Floor_Name").ToString.Trim()
Which accesses the ToString method of the data row and calls Trim() on it. You aren't actually calling ToString. Change it to
Btn.Text = Dr("Floor_Name").ToString().Trim()
and it should work.

Is there a "Restore Down" event in VB.NET

What event would fit when I click the "Restore Down" button in the title bar then it restores down the main form together with the other form with the specific size I declared.
I am new to vb.net and still exploring new functions. Please help!
Apologizes for c# solution, perhaps this will help you to convert it to VB.Net. I don't know any better solution available but this should work.
private FormWindowState? previousWindowState;
protected override void OnSizeChanged(EventArgs e)
{
if (this.Bounds == this.RestoreBounds && previousWindowState.HasValue && previousWindowState.Value == FormWindowState.Maximized)
{
Console.WriteLine("Restored down");
}
previousWindowState = this.WindowState;
base.OnSizeChanged(e);
}
Adapted Srirams answer to vb.net
Private Sub MotionManagerDialog_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SizeChanged
If Me.Bounds.Equals(Me.RestoreBounds) And Not PreviousWindowState.Equals(Nothing) And
PreviousWindowState.Equals(System.Windows.Forms.FormWindowState.Maximized) Then
' Captures restore down action
End If
PreviousWindowState = Me.WindowState
End Sub
To clarify Wylie's answer: You also need to declare PreviousWindowState somewhere:
Dim PreviousWindowState As FormWindowState

Is there a way to force a DataGridView to fire its CellFormatting event for all cells?

We use the CellFormatting event to colour code cells in various grids all over our application.
We've got some generic code which handles export to Excel (and print) but it does it in Black & White. Now we want to change this and pick up the colour from the grids.
This question & answer has helped (and it works) ... except there's a problem with larger grids that extend beyond a single screen. The portions of the grid which haven't yet been displayed on screen are (logically) never getting their CellFormatting code fired, and so their underlying colour never gets set. As a result, in Excel, the colour coding fizzles out half way down the page.
Seems there are three solutions:
1) Tell the user he has to scroll to all parts of the grid before doing an Export to Excel. Ha! Not a serious solution
2) Programmatically scroll to all parts of the grid before doing an Export to Excel. Only slighly less horrible than (1)
3) In our Export to Excel code, fire something at the top which tells the DataGridView to paint/format its entire area e.g.
MyDataGridView.FormatAllCells()
Is there something that does something like this???
Oh, and there is a fourth option but this will involve touching a massive amount of existing code:
4) Stop using CellFormatting event, format the cells at load time. Problem with this is we'd have to retool every grid in our application since CellFormatting is the way we've done it since year dot.
As noted in the other answers, accessing the DataGridViewCell.FormattedValue is indeed an easy way to force the CellFormatting event to be (re-)called for a specific cell. In my case, however, this property was also leading to undesirable side-effects involving the auto-resizing of the columns. While searching a long time for a workable solution, I finally encountered the following magic methods that work perfectly: DataGridView.Invalidate(), DataGridView.InvalidateColumn(), DataGridView.InvalidateRow(), and DataGridView.InvalidateCell().
These 4 methods force the CellFormatting event to be re-called only for the specified scope (cell, column, row, or whole table), and also without causing any nasty auto-resizing artifacts.
I have a possible solution - In your export function access the Cell.FormattedValue property of each cell. According to Microsoft, this forces the CellFormatting event to fire.
Assuming, as #DavidHall suggests, there is no magic .FormatAllCells our only option is to stop using CellFormatting.
However, new problem here is that applying cell style formatting during load doesn’t seem to have any effect. Lots of posts out there if you Google it. Also they point out that if you put the same code under a button on the form and click it after loading (instead of in the load, the code will work ... so the grid has to be visible before styling can apply). Most advice on the topic suggests you use ... drumroll ... CellFormatting. Aargh!
Eventually found a post which suggests using the DataBindingComplete event of the grid. And this works.
Admittedly, this solution is a variant of my unwanted option "4".
I had the same problem and I've ended up with something quite similar to your solution #4.
like you, I've used the DataBindingComplete event. but, Since I've used Extension method, the changes in the existing code are bearable:
internal static class DataGridViewExtention
{
public static void SetGridBackColorMyStyle(this DataGridView p_dgvToManipulate)
{
p_dgvToManipulate.RowPrePaint += p_dgvToManipulate_RowPrePaint;
p_dgvToManipulate.DataBindingComplete += p_dgvToManipulate_DataBindingComplete;
}
// for the first part - Coloring the whole grid I used the `DataGridView.DataBindingComplete` event:
private static void p_dgvToManipulate_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow objCurrRow in ((DataGridView)sender).Rows)
{
// Get the domain object from row
DomainObject objSelectedItem = (DomainObject)objCurrRow.DataBoundItem;
// if item is valid ....
if objSelectedItem != null)
{
// Change backcolor of row using my method
objCurrRow.DefaultCellStyle.BackColor = GetColorForMyRow(objSelectedItem);
}
}
}
// for the second part (disabling the Selected row from effecting the BackColor i've setted myself, i've used `DataGridView.RowPrePaint` event:
private static void p_dgvToManipulate_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
// If current row about to be painted is selected by user
if (((DataGridView)sender).Rows[e.RowIndex].Selected)
{
// Get current grid row
var objGridRow = ((DataGridView)sender).Rows[e.RowIndex];
// Get selectedItem
DomainObject objSelectedItem = (DomainObject)objGridRow.DataBoundItem;
// if item is valid ....
if (objSelectedItem != null && objSelectedItem.ObjectId != 0)
{
// Set color for row instead of "DefaultCellStyle" (same color as we used at DataBindingComplete event)
objGridRow.DefaultCellStyle.SelectionBackColor = GetColorForMyRow(objSelectedItem);
}
// Since the selected row is no longer unique, we need to let the used to identify it by making the font Bold
objGridRow.DefaultCellStyle.Font = new Font(((DataGridView)sender).Font.FontFamily, ((DataGridView)sender).Font.Size, FontStyle.Bold);
}
// If current row is not selected by user
else
{
// Make sure the Font is not Bold. (for not misleading the user about selected row...)
((DataGridView)sender).Rows[e.RowIndex].DefaultCellStyle.Font = new Font(((DataGridView)sender).Font.FontFamily,
((DataGridView)sender).Font.Size, FontStyle.Regular);
}
}
}
A possible solution if you do want to reuse the formatting provided during the Cellformatting-event (e.g. the cellstyle-elements like fontbold and backgroundcolor). These cellstyles seem to be only available between the 'cellformatting' and 'cellpainting' events but not in the datagridview-cell's style itself..
Capture the cellstyles during the cellformatting-event with a second handler like this:
in the exportmodule add a shared list, array or dictionary to store the cellstyles:
Dim oDataGridFormattingDictionary as Dictionary(Of String, DataGridViewCellStyle) = nothing
initialize the dictionary and add a second handler to the datagridview in your printing or export-code. In vb.net something like this:
oDataGridFormattingDictionary = New Dictionary(Of String, DataGridViewCellStyle)
AddHandler MyDatagridviewControl.CellFormatting, AddressOf OnPrintDataGridView_CellFormatting
Add the code for the handler
Private Sub OnPrintDataGridView_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs)
If e.RowIndex > -1 AndAlso e.ColumnIndex > -1 AndAlso Not e.CellStyle Is Nothing Then
If Not oDataGridFormattingDictionary Is Nothing andalso oDataGridFormattingDictionary.ContainsKey(e.RowIndex & "_" & e.ColumnIndex) = False Then
oDataGridFormattingDictionary.Add(e.RowIndex & "_" & e.ColumnIndex, e.CellStyle)
End If
End If
End Sub
Very important: to make sure the original cellformating-event (AND the second cellformatting-handler after that) are actually called you have to request the formattedvalue for each cell that you want to print (e.g.
oValue = Datagridview.rows(printRowIndex).Cells(printColumnIndex).FormattedValue)
!
When printing you can now check if the cell has formatting. E.g.:
if not oDataGridFormattingDictionary is nothing andalso oDataGridFormattingDictionary.ContainsKey(printRowIndex & "_" & printColumnIndex) Then
... the cellstyle is accesible via:
oDataGridFormattingDictionary(printRowIndex & "_" & printColumnIndex)
end if
at the end of the export or printcode remove the handler and set the dictionary to nothing
RemoveHandler DirectCast(itemToPrint.TheControl, DataGridView).CellFormatting, AddressOf OnPrintDataGridView_CellFormatting
oDataGridFormattingDictionary = nothing

Connecting 2 Textboxes values temporarily

I want to create 2 Textboxes (txt1, txt2) and when I write in txt1 then txt2 should reflect the same text what i typed in txt1. For ex. When we create a new Solution in Visual Studio Professional, what name we give to Project, same name appears for Solution. But if we edit solution name, link between the 2 textboxes breaks.
I do have some idea about it, to do it with textChange event or in fact many similar events, but not sure that they are the best methods.
I am using Winforms, C# 4.0, Visual Studio 2010 (if this info matters)
If my question is not clear, just make a comment I will try to elaborate.
Thanks.
With the given definition of the requirement, adding TextChanged EventHandlers is the way to go.
private void txt1_TextChanged(object sender, EventArgs e)
{
txt2.Text = txt1.Text;
}
private void txt2_TextChanged(object sender, EventArgs e)
{
txt1.Text = txt2.Text;
}
Consider adding an event handler for txt1_TextChanged and txt2_KeyPress.
txt1_TextChanged would assign txt2.Text: txt2.Text = "c:\" + txt1.Text;
txt2_KeyPress would unsubscribe txt1_TextChanged: txt1.TextChanged -= txt1_TextChanged;.
I solved it, so thought to post it here
txt1_TextChanged(obje....)
{
txt2.Text = txt1.Text;
}
txt2_TextChanged(objec...)
{
if(txt2.Focused)
{
txt1.TextChanged -= new EventHandler(txt1_TextChanged);
}
}
Hope it helps.

Resources