This question already has answers here:
How to clear the text of all textBoxes in the form?
(10 answers)
Clear all TextBox in Window
(1 answer)
Closed 6 years ago.
Is there a way to clear textboxes at once when they have been renamed as txtFName, txtMName etc... They may have variety of names beginning with txt. Is this possible? Something like
private void btnReset_Click(object sender, EventArgs e)
{
txtFname.Clear();
txtLName.Clear();
txtUsername.Clear();
txtPasswrd.Clear();
/*So many textboxes to be cleared*/
}
to be replaced with
private void ClearTextboxes(object obj)
{
/*codes to clear textboxes*/
}
and then we can call it in the button click event
private void btnReset_Click(object sender, EventArgs e)
{
ClearTextboxes();
txtFname.Focus();
}
this method clear all textbox from WinForm
void ClearTextboxes(System.Windows.Forms.Control.ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl is TextBox)
((TextBox)ctrl).Text = string.Empty;
ClearTextboxes(ctrl.Controls);
}
}
and you can call it
private void btnReset_Click(object sender, EventArgs e)
{
ClearTextboxes();
txtFname.Focus();
}
You can iterate through all textbox in your VisualTree like this:
foreach (TextBox txtBx in FindVisualChildren<TextBox>(this))
{
txtBx.Clear();
}
FindVisualChildren :
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
As an argument you can pass any parent it can be StackPanel, or Grid or whole window.
One way using event is:
using System;
using System.Windows.Forms;
namespace textBoxs
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Subscribe();
}
private event Action ClearAll;
void Subscribe()
{
ClearAll += tbA.Clear;
ClearAll += tbB.Clear;
ClearAll += tbC.Clear;
}
private void button1_Click(object sender, EventArgs e)
{
ClearAll();
}
}
}
Related
I have a button list which is a button array. Please tell me how to change the color of every button array button when I hover the mouse. I had tried to use loops in the event button when I used loop, but when I hover the mouse on the other button, this button still changes color although I never set any event for it.
I hope this code sample will be helpful to you
public partial class Form1 : Form
{
private Button[] buttonsArray = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GetButtonsArray();
if (buttonsArray != null)
{
foreach (Button button in buttonsArray)
{
button.MouseEnter += button_MouseEnter;
button.MouseLeave += button_MouseLeave;
}
}
}
private void GetButtonsArray()
{
// This is an example to fill array of buttons.
// You have to fill array in your way, according to your task.
foreach (Control control in this.Controls)
if (control is Button)
buttonsArray = buttonsArray.Append(control as Button);
}
private void button_MouseEnter(object sender, EventArgs e)
{
if (sender is Button)
(sender as Button).BackColor = Color.Yellow;
}
private void button_MouseLeave(object sender, EventArgs e)
{
if (sender is Button)
(sender as Button).BackColor = SystemColors.Control;
}
}
public static class Extensions
{
public static T[] Append<T>(this T[] array, T item)
{
if (array == null)
return new T[] { item };
T[] result = new T[array.Length + 1];
array.CopyTo(result, 0);
result[array.Length] = item;
return result;
}
}
In my WPF application a "global" search box appears when hitting Ctrl+Space. It behaves like Spotlight in Mac OS when hitting Command+Space.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public static RoutedCommand OpenSpotlight { get; set; } = new RoutedCommand();
public MainWindow()
{
OpenSpotlight.InputGestures.Add(new KeyGesture(Key.Space, ModifierKeys.Control));
}
private void OpenSpotlight_Execute(object sender, ExecutedRoutedEventArgs e)
{
// Code which opens the search box ...
}
}
MainWindow.xaml
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.OpenSpotlight}" Executed="OpenSpotlight_Execute"/>
</Window.CommandBindings>
Works fine, except one problem: when any button is focused, hitting Ctrl+Space triggers the button to be clicked because Space key is being hit.
Is there any way to omit this behaviour? I think of changing/removing the focus globally when Ctrl key is hit but don't know how this can be implemented ...
Instead of using a RoutedCommand and a CommandBinding, you could just handle the PreviewKeyDown event:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PreviewKeyDown += OnPreviewKeyDown;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space
&& (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
e.Handled = true;
// Code which opens the search box ...
}
}
}
This solution doesn't require you to add anything to the XAML markup.
I haven't tried this, but seems quite logical to me.
You can handle the KeyDown and/or PreviewKeyDown event of a button and skip the Space press. Something like this could work :
private void GlobalButton_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
Wondering how you'ld do this for all the buttons? Here's a function to find a control of a given type:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T :
DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Simply loop through the buttons on window_load or similar events:
foreach (Button btn in FindVisualChildren<Button>(this))
{
btn.KeyDown += GlobalButton_PreviewKeyDown;
btn.PreviewKeyDown += GlobalButton_PreviewKeyDown;
}
Hopefully this helps.
I have an issue with a custom event i have created. I have made a Usercontrol that looks the following:
public partial class UCListView : UserControl {
public UCListView() {
InitializeComponent();
}
public event EventHandler SubmitClick;
public event EventHandler MouseButtonUpEvent;
private void SubmitButton_OnClick(object sender, RoutedEventArgs e) {
if (SubmitClick != null)
SubmitClick(this, e);
}
private void MouseButtonUp(object sender, RoutedEventArgs e) {
if (MouseButtonUpEvent != null) {
MouseButtonUpEvent(this, e);
}
}
}
Here is the MouseButtonUp event i have.
The following is where i listen to the event:
public partial class RoundsteelWindow : WindowControls {
private UCListView uc;
public RoundsteelWindow() {
InitializeComponent();
uc = new UCListView();
uc.SubmitClick += new EventHandler(ButtonPressed);
uc.MouseButtonUpEvent += new EventHandler(MousePressed);
stkTest.Children.Add(uc);
base.Test<RoundSteel>(uc, "Roundsteel");
}
}
Here is the WindowControls, where the MousePressed method can be seen. This is the same as the code snippet beneath this code. Really don't see the issue:
public abstract class WindowControls : Window {
public IMaterialWith14Elements _ReturnObject { get; set; }
public double amount { get; set; }
private UCListView _uc;
public void Test<T>(UCListView uc, string type) where T: IMaterialWith14Elements, new() {
_uc = uc;
List<T> test = MaterialLogic.GetList(type) as List<T>;
foreach (T material in test) {
uc.listView.Items.Add(material.Name);
}
}
private string str;
public void MousePressed(object sender, EventArgs eventArgs) {
var item = (sender as ListView).SelectedItem;
if (item != null) {
_ReturnObject = _uc.listView.SelectedItems as FlatSteel ;
str = item.ToString();
_uc.amountText.IsEnabled = true;
}
}
public void ButtonPressed(object sender, EventArgs e) {
if (!string.IsNullOrEmpty(_uc.amountText.Text)) {
amount = _uc.amountText.Text.customParseToDouble();
this.Close();
}
else {
MessageBox.Show("Indtast venligst en værdi.");
}
}
}
Now the problem is the following: With the following code it is working, but this class is not using the windowcontrols. It is called by another class which handles all of the buttons.
private void flatsteelListView_PreviewMouseLeftButtonUp(object sender, RoutedEventArgs e) {
var item = (sender as ListView).SelectedItem;
if (item != null) {
_returnObject = flatsteelListView.SelectedItems as FlatSteel;
str = item.ToString();
amountTextbox.IsEnabled = true;
FindObject(str);
}
}
The first picture shows the working window. This is where there is not used a usercontrol. Actually this is a previous issue i have worked with and got help with here on stackoverflow Help for thisissue.
The second picture is showing the next window using the usercontrol that has been created. The button event works and closes the window. Here comes then the issue, when the listview item is pressed. It is doing the same thing as on the first picture(where it works), but it is giving me a null reference, which doesn't make any sense to me. I have also checked the object sender to see if there was a difference between the sender of these two different windows.
I simply can't figure out why this is not working.
greetings darophi
Your sender is an object of UCListView class which is inherited from UserControl and you are trying to use it like ListView. So as result of operation (sender as ListView) you get null because sender is not an instance of ListView class and not inherits it.
In my winform application I have one form that creates other forms during a for loop. This parent form remains hidden is there purely for processing.
I moved the processing code away from the program class because Application.Run didn't seem to place nice in a loop as more than one instance would be open.
When the child forms are done with they are closed. What I want to know is whether I can get the application to exit when these forms are closed even though the parent form is still open. I have tried exposing a List<bool> on the parent form to store which of the forms have closed but the child forms cannot access the list due to the parent form not having an instance name - it is called by Application.Run(new FormProcessor(args));
More generally I guess I am asking is there a way to access properties of the parent form from the child forms.
Inject a reference to the parent form in the constructor of each child form, thus allowing access to it.
Or when each child form is created add a reference to a list in the parent form then run a background task to wait for all the child forms to close. You could do this by subscribing to the form closed event on each of the child forms and waiting for these to fire
A simple example of what I have tried to show in the comments would be the following.
You create an extra class that handles the registration to the FormClosed event as for example:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Forms;
namespace wfAutoClose {
public class FormSubscriber : INotifyPropertyChanged, IDisposable {
public event PropertyChangedEventHandler PropertyChanged;
private readonly IList<Form> _forms = new ObservableCollection<Form>();
public IList<Form> Forms {
get {
return _forms;
}
}
public int FormCount {
get {
return _forms.Count;
}
}
private void RaisePropertyChanged(string propertyName) {
var localEvent = PropertyChanged;
if (localEvent != null) {
localEvent.Invoke( this, new PropertyChangedEventArgs( propertyName: propertyName ) );
}
}
private void OnChildFormClosed(object sender, FormClosedEventArgs e) {
Forms.Remove( sender as Form );
}
private void SubscribeToFormClosedEvent(Form childForm) {
childForm.FormClosed += OnChildFormClosed;
}
private void UnsubscribeFromFormClosedEvent(Form childForm) {
childForm.FormClosed -= OnChildFormClosed;
}
private void OnChildFormCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (e.OldItems != null) {
foreach (var item in e.OldItems) {
UnsubscribeFromFormClosedEvent( item as Form );
}
}
if (e.NewItems != null) {
foreach (var item in e.NewItems) {
SubscribeToFormClosedEvent( item as Form );
}
}
RaisePropertyChanged( "FormCount" );
}
public void Dispose() {
( Forms as INotifyCollectionChanged ).CollectionChanged -= OnChildFormCollectionChanged;
}
public FormSubscriber() {
( Forms as INotifyCollectionChanged ).CollectionChanged += OnChildFormCollectionChanged;
}
}
}
this one can then be used inside your parent form, where you simply add the forms in your loop, and your parent form can register itself to the INotifyPropertyChanged event of the FormSubscriber. When there are no more forms available, it will show FormCount == 0 where this is the place you will exit from your application (by either calling Application.Exit() or this.Close())
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace wfAutoClose {
public partial class Form1: Form {
FormSubscriber formSubscriber = new FormSubscriber();
public Form1() {
InitializeComponent();
formSubscriber.PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged( object sender, PropertyChangedEventArgs e ) {
if (formSubscriber.FormCount == 0) {
Application.Exit();
}
}
private void Form1_Load( object sender, EventArgs e ) {
for ( int i = 0; i < 3; i++ ) {
Form form = new Form2() { Text = "Dynamic Form " + i };
form.Show();
formSubscriber.Forms.Add( form );
}
}
private void Form1_FormClosed( object sender, FormClosedEventArgs e ) {
formSubscriber.Dispose();
}
}
}
Of course, in my example they are just basic windows, and I do not care about any threading or other GUI specifics, but it should show you the basics of what you could do with the event registration and the usage of the ObservableCollection<T> (see FormSubscriber)
Use ApplicationContext and subscribe to the FormClosed() event of all the child forms. Check the Application.OpenForms collection and Exit() when appropriate...
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyContext());
}
}
public class MyContext : ApplicationContext
{
public MyContext()
{
// Open your Forms...
for(int i = 1; i <= 5; i++)
{
Form frm = new Form();
frm.Text = "Form #" + i.ToString();
frm.FormClosed += Frm_FormClosed;
frm.Show();
}
}
private void Frm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0)
{
Application.Exit();
}
}
}
Simplest of all would be to keep information about opened/closed forms in some other global class like:
public static class Helper
{
public static List<int> ChildFormsOpened { get; private set; }
static Helper()
{
ChildFormsOpened = new List<int>();
}
}
You can simply add form hashcode when you open it. You can do this in ctor or load event handler of your child form when it is opened :
Helper.ChildFormsOpened.Add(this.GetHashCode());
So at some point in your code you can remove the form that is closing from collection and check if all other forms are closed as well. If they are, so you can close your application by invoking Application.Exit() method:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Helper.ChildFormsOpened.Remove(this.GetHashCode());
if(Helper.ChildFormsOpened.Count < 1) Application.Exit();
}
Thanks to all who helped with this. I have come up with an answer that works for me. I've added an event handler on the back of form closed. The origList variable stores the original data for formList otherwise the foreach will proceed to the next entry of the list which it may have removed.
for ( int i =0; i < formList.Count; i++)
{
string formName = formList[i];
Form1 frm = (new Form1(formName...);
frm.Show();
string contextName= formName;
frm.FormClosed += new FormClosedEventHandler((sender, e) => FrmClosed_Event(sender, e, contextName));
}
public void FrmClosed_Event(object sender, FormClosedEventArgs e, string name)
{
foreach(string thisForm in origList)
{
if (thisForm == name)
{ formList.Remove(thisForm); }
}
if (formList.Count == 0)
{ Application.Exit(); }
}
I have the following control, which just has a TreeView and ToolStrip dropped on it:
public partial class MyTreeView : UserControl
{
private string _nodeName;
public string NodeName { get { return _nodeName;} }
public MyTreeView()
{
InitializeComponent();
}
private void trv_AfterSelect(object sender, TreeViewEventArgs e)
{
if (e.Node == null || e.Node.Parent == null || e.Node.Parent.Parent == null)
return;
nodeName = e.Node.Parent.Parent.Text + #"\" + e.Node.Parent.Text + #"\" + e.Node.Text;
}
}
Then in my main form, which contains an instance of MyTreeView, I tried to add a Click event there:
private void mtv_Click(object sender, EventArgs e)
{
MessageBox.Show(mtv.NodeName.ToString());
}
The AfterSelect event fires and nodeName contains the expected value, but Click does not trigger.
Ultimately I'm going to be loading a file and displaying its contents in a textbox when the TreeView selection changes, but I can't figure out how to 'notify' the form the selection changed happened on the custom control.
Try this
public partial class MyTreeView : UserControl
{
public delegate void ValueSelectedHandler(object sender, EventArgs e, string value);
public event ValueSelectedHandler OnValueSelected;
private string _nodeName;
public string NodeName { get { return _nodeName;} }
public MyTreeView()
{
InitializeComponent();
}
private void trv_AfterSelect(object sender, TreeViewEventArgs e)
{
if (e.Node == null || e.Node.Parent == null || e.Node.Parent.Parent == null)
return;
nodeName = e.Node.Parent.Parent.Text + #"\" + e.Node.Parent.Text + #"\" + e.Node.Text;
if(OnValueSelected!=null)
{
OnValueSelected(sender, e, nodeName);
}
}
}
Now in your form
public Form1()
{
InitializeComponent();
myTreeView1.OnValueSelected += ValueSelected;
}
private void ValueSelected(object sender, EventArgs e, string value)
{
MessageBox.Show(value);
}
you may try this.
rewrite your control like this.
public partial class MyTreeView : UserControl
{
//create a custom event
[Browsable(true)]
public event TreeViewEventHandler AfterSelect;
public MyTreeView()
{
InitializeComponent();
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if (AfterSelect != null) {
//raise the event , as it is subscribed may be in winform
AfterSelect.Invoke(sender, e);
}
}
}
and now in win form subscirbe after Select Event of MytreeView Control.
public Form2()
{
InitializeComponent();
//subscribe myTreeView1.AfterSelect event
myTreeView1.AfterSelect += new TreeViewEventHandler(myTreeView1_AfterSelect);
}
private void myTreeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
//cast sender into TreeView
TreeView tree = sender as TreeView;
if (tree != null) {
//do your logic here
}
}