I have a form with two panels that each have a [Save] button.
How can I validate all of the controls inside each panel separately?
I was hoping that the Panel class would have a Validate() method but it doesn't. It's also not a ContainerControl so it also doesn't have a ValidateChildren method.
What's the best way to accomplish this?
If you set your Form's AutoValidate mode to EnableAllowFocusChange, and presuming you have validating events hooked up to each of the controls inside your panel, something like this:
private void tb_Validating(object sender, CancelEventArgs e)
{
TextBox tb = sender as TextBox;
if (tb != null)
{
if (tb.Text == String.Empty)
{
errorProvider1.SetError(tb, "Textbox cannot be empty");
e.Cancel = true;
}
else
errorProvider1.SetError(tb, "");
}
}
Then on the Click handler for your save button, you can just do this:
private void SaveButton_Click(object sender, EventArgs e)
{
foreach (Control c in panel1.Controls)
c.Focus();
// If you want to summarise the errors
StringBuilder errorSummary = new StringBuilder();
foreach (Control c in panel1.Controls){
String error = errorProvider1.GetError(c);
if (error != String.Empty)
errorSummary.AppendFormat("{0}{1}", errorProvider1.GetError(c), Environment.NewLine);
}
if(errorSummary.Length>0)
MessageBox.Show(errorSummary.ToString());
}
That will cause the validation to fire on each of the controls within the panel.
Related
I have a TextChanged event attached to a TextBox in a Windows Form. How to make sure if a particular call to that event wasn't triggered programmatically rather by user interacting with the TextBox?
I would like to extend #rw_'s solution a little. Inside your TextBox event handler,
private void txt_TextChanged(object sender, EventArgs e)
{
if (!(sender is null) &&((TextBox)sender).ContainsFocus)
{
//Code if triggered by Click event
}
else
{
//Code if triggered programmatically
}
}
This will help your program adjust to the case where sender object is not null for some reason.
I am unsure about what your question means. I'll split my answer.
If you want to call the text changed function programmatically and differ when it was called by user interactivity or if it was called programmatically:
Assuming that when you call the function programmatically you pass null on sender and event args txt_TextChanged(null,null);, you could use this solution:
private void txt_TextChanged(object sender, EventArgs e)
{
if(sender == null)
{
// triggered programmatically
}
else
{
// triggered by the user. sender object is the textbox interacted by the user
}
}
If you want to change the text programmatically without triggering the event:
this.txt.TextChanged -= new System.EventHandler(this.txt_TextChanged);
txt.Text = "bar";
this.txt.TextChanged += new System.EventHandler(this.txt_TextChanged);
This is a common problem. You can set a flag on your form before updating the value and then check it in your event handler:
handleEvent = false;
TextBox1.Text = "foo";
handleEvent = true;
Then in your handler, check the flag:
private void TextBox1_TextChanged(object sender, EventArgs e)
{
if(handleEvent)
{
// do stuff
}
}
I have an attached property called "SelectAllOnFocus". Values of true/false.
public static class TextBoxProps
{
private static void MyTextBoxKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
((TextBox)sender).Text = string.Empty;
}
}
public static void SetSelectAllOnFocus(DependencyObject dependencyObject, bool selectAllOnFocus)
{
if (!ReferenceEquals(null, dependencyObject))
{
dependencyObject.SetValue(SelectAllOnFocus, selectAllOnFocus);
}
}
public static bool GetSelectAllOnFocus(DependencyObject dependencyObject)
{
if (!ReferenceEquals(null, dependencyObject))
{
return (bool)dependencyObject.GetValue(SelectAllOnFocus);
}
else
{
return false;
}
}
private static void OnSelectAllOnFocus(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool selectAllOnFocus = (bool)e.NewValue == true;
var theTextBox = d as TextBox;
if (selectAllOnFocus && theTextBox != null)
{
theTextBox.PreviewMouseDown -= MyTextBoxMouseEnter; theTextBox.PreviewMouseDown += MyTextBoxMouseEnter;
}
}
private static void MyTextBoxMouseEnter(object sender, MouseEventArgs e)
{
((TextBox)sender).SelectAll();
e.Handled = false;
}
public static readonly DependencyProperty SelectAllOnFocus
= DependencyProperty.RegisterAttached("SelectAllOnFocus", typeof(bool), typeof(TextBoxEscapeProperty),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnSelectAllOnFocus)));
}
What happens is the following:
The PreviewMouseDown event gets triggered.
The MyTextBoxMouseEnter method gets called.
The SelectAll() Method gets called.
When I do a "watch" on ((TextBox)sender).SelectedText, the value is correct (meaning whatever is in the textbox is showing up as selectedText).
The textbox itself is unchanged. No text is selected.
This is part of a general WPF style. All textboxes in the application should receive this property and it's associated behavior.
I'm stumped. Any ideas?
Thanks
What happens if you call ((TextBox)sender).UpdateLayout(); immediately after the SelectAll command? Or maybe you need to set the Keyboard focus to the text box.
It might be a better option to use something like this, which works if the text box is being selected with the mouse or the keyboard. (You'll need to modify it to check your "SelectAllOnFocus" property)
In your App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
// Select the text in a TextBox when it receives focus.
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent, new RoutedEventHandler(SelectAllText));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent, new RoutedEventHandler(SelectAllText));
base.OnStartup(e);
}
void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
i have a field in my database for detect font syle of a row.
font syle is Regular where it is true.
I want to changing my row style when select it. i write this :
private void myGrid_SelectionChanged(object sender, EventArgs e)
{
DataBaseComponent.EditFieldofObject(object1.Serial, true);
if (myGrid.SelectedRows[0].VisualElement != null)
myGrid.SelectedRows[0].VisualElement.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(178)));
myGrid.SelectedRows[0].Cells["myField"].Value = true;
}
but it doesnot work and i must bind grid again to see this change.
Why not use ItemDataBound instead of SelectionChanged? This will work for your needs.
protected void myGrid_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem dataBoundItem = (GridDataItem)e.Item;
if (dataBoundItem["ColumnName"].Text.ToString() == "True")
{
// Do something here
}
}
}
There is a good article on Telerik explaining it.
I'm trying to get a rowindex of row at which I right clicked to call a contextmenu.
DatagridView's property contextmenu is set to this contextmenu.
Is it possible in some simple way?
Best regards
Yes, you need to handle the MouseDown event for your DataGridView and then use the HitTest method to return row and/or column index for the given coordinates.
For example:
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
DataGridView.HitTestInfo hit = dataGridView1.HitTest(e.X, e.Y);
if (hit.Type == DataGridViewHitTestType.Cell)
{
Console.WriteLine(hit.RowIndex);
}
}
}
I change the selection in the CellContextMenuStripNeeded event and then use the SelectedRows member to find it.
private void dataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
{
var Dgv = sender as DataGridView;
if (Dgv != null)
{
// Change the selection to reflect the right-click
Dgv.ClearSelection();
Dgv.Rows[e.RowIndex].Selected = true;
}
}
private void myToolStripMenuItem_Click(object sender, EventArgs e)
{
// Now pick up the selection as we know this is the row we right-clicked on
if (dataGridView.SelectedRows.Count > 0)
{
DoSomethingAmazing(dataGridView.SelectedRows[0]);
}
}
This also has the desired effect of highlighting a row that you r-click on.
This is the case:
I trying to do a extra format to my tooglesbuttons
private void PanelToggles_Checked(object sender, RoutedEventArgs e)
{
ToggleButton currentTB = sender as ToggleButton;
if (currentTB != null)
{
foreach (UIElement tb in GridToggles.Children)
{
MessageBox.Show(tb.GetType().ToString());
(tb as ToggleButton).IsChecked = false;
}
currentTB.IsChecked=true;
currentTB.FontWeight = FontWeights.Bold;
//implementation
}
}
It throws StackOverFlowException, some ideas?
Just a guess, but it seems like PanelToggles_Checked is an event called infinite times and the reason could be because you are doing currentTB.IsChecked = true; in your conditional statement which triggers the event to be called again and again....