TextBox resets text when tabbing out ot other controls - winforms

I have a form with several controls. There a situtions where 'textBoxOtherRelationship' is disable and the text is set to string.empty. But when I then got to another control and tab out the data appears again,while the control remains disabled.
textBoxOtherRelationship.DataBindings.Add(new Binding("Text", _binder, "RelationshipNotes"));
private void ComboBoxRelationShipSelectedValueChanged(object sender, EventArgs e)
{
if ((Constants.Relationship)comboBoxRelationShip.SelectedItem.DataValue == Constants.Relationship.Other)
{
textBoxOtherRelationship.Enabled = true;
if (_formMode != ActionMode.ReadOnly)
{
textBoxFirstName.BackColor = Color.White;
}
}
else
{
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null;
textBoxOtherRelationship.Text = string.Empty;
if (_formMode != ActionMode.ReadOnly)
{
textBoxFirstName.BackColor = Color.LightYellow;
}
}
}

Hmm.. so I see this line here:
textBoxOtherRelationship.DataBindings.Add(
new Binding("Text", _binder, "RelationshipNotes"));
which tells me that you've got binding set up between the Text property on the textBoxOtherRelationship and a property called "RelationshipNotes" on the datasource _binder.
Great.
So, I'm assuming that the two-way binding works just fine and that when you type something into the textBoxOtherRelationship and that control loses focus the underlying RelationshipNotes property is getting updated as well, right?
Now, looking at your code there, I don't think the underlying datasource is being updated when you set the Text property to string.Empty because that usually doesn't happen until the textbox loses focus and you've disabled the control.
If you add:
textBoxOtherRelationship.DataBindings[0].WriteValue();
after you set the value to string.Empty that string.Empty value will get stored back to the datasource because the databinding will know there is something to update. Programmatically, it doesn't.
I see you have this line:
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null; <<<----------------------
textBoxOtherRelationship.Text = string.Empty;
Is _model.RelationshipNotes what is ultimately supposed to be bound to that textbox?

The SelectedIndexChanged event doesn't commit the databindings until after the control loses focus, so the quick fix is to write the value first in your event:
private void ComboBoxRelationShipSelectedValueChanged(object sender, EventArgs e)
{
if (comboBoxRelationShip.DataBindings.Count > 0) {
comboBoxRelationShip.DataBindings[0].WriteValue();
if ((Constants.Relationship)comboBoxRelationShip.SelectedItem.DataValue ==
Constants.Relationship.Other) {
textBoxOtherRelationship.Enabled = true;
if (_formMode != ActionMode.ReadOnly) {
textBoxFirstName.BackColor = Color.White;
}
} else {
textBoxOtherRelationship.Enabled = false;
_model.RelationshipNotes = null;
textBoxOtherRelationship.Text = string.Empty;
if (_formMode != ActionMode.ReadOnly) {
textBoxFirstName.BackColor = Color.LightYellow;
}
}
}
}

Related

Determine whether the active check box is checked in Winforms

I am developing a Windows Forms Application using Visual Studio in Visual C++. My form has 96 check boxes on it. Rather than create 96 Click events, I believe that there's a way to create a single Click event that is called when any check box is clicked. Within the Click event, I need to determine whether the active checkbox is Checked or Not Checked. While this should be easy, I can't seem to figure it out!
I got it to work with the code below, but I'm sure there's a better way.
if (sender == checkBox_D1)
{
if (checkBox_D1->Checked)
isChecked = true;
}
else if (sender == checkBox_D2)
{
if (checkBox_D2->Checked)
isChecked = true;
}
else
return; // Invalid sender - should not get here!
if (isChecked)
{
// Do something
}
else
{
// Do something else
}
I also tried the code below but activeCheckBox is not a Checkbox object so it doesn't work.
Control^ activeCheckBox = ActiveControl;
activeCheckBox->Text returns the Text property of the Checkbox
activeCheckBox->Checked doesn't compile. The error is 'Checked' : is not a member of 'System::Windows::Forms::Control'
It seems like sender has the data that I need but I don't know how to access it.
Is there a way to declare a Checkbox as follows?
CheckBox activeBox;
and then assign activeBox to the Checkbox that has the focus
activeBox = ???
// Then just need to do this!
if (activeBox.Checked)
isChecked = true;
Thank you for the help.
Yes you can reuse the same function for all your Check boxes.
void App3::ItemPage::checkBox_Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CheckBox^ activeCheckBox = safe_cast<CheckBox^>(sender);
if (activeCheckBox->Checked)
{
if (activeCheckBox->Name == "checkBox_D1") {
//Do something when this check box is clicked.
}
if (activeCheckBox->Name == "checkBox_D2") {
//Do something when this check box is clicked.
}
}
}
For all checBoxes you will assign the same CheckedChanged event:
checkBox1.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
checkBox2.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
//...
//...
checkBox95.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
checkBox96.CheckedChanged += newCheckBoxCheckedOrUnchecked_CheckedChanged;
Checks the state of all checkBoxes:
private void newCheckBoxCheckedOrUnchecked_CheckedChanged(object sender, EventArgs e)
{
foreach (Control control in this.Controls)
{
if (control.GetType() == typeof(CheckBox))
{
var checkBox = (CheckBox) control;
var checkBoxName = checkBox.Name; // To know which checkbox we are talking about
var checkBoxIsChecked = checkBox.Checked;
// Do your stuff
MessageBox.Show(checkBoxName + #" is " + (checkBoxIsChecked ? "checked" : "not checked"));
}
}
}
Checks the state of only the checkBox where the value was changed:
private void newCheckBoxCheckedOrUnchecked_CheckedChanged(object sender, EventArgs e)
{
var checkBox2 = (CheckBox)sender;
var checkBoxName2 = checkBox2.Name; // To know which checkbox we are talking about
var checkBoxIsChecked2 = checkBox2.Checked;
// Do your stuff
MessageBox.Show(checkBoxName2 + #" is " + (checkBoxIsChecked2 ? "checked" : "not checked"));
}

How to uncheck checkbox in datagridview using Entity framework

I have datagridview on winform. It is bound to result from below code:
PoolEntities db = new PoolEntities();
var Result = db.General_Pool_Detail.Where(g => g.Pool_Name == cbxGLType.SelectedValue && g.Mapped_Date == dt).Select(s=>
new { Selected = true, s.Gen_Pool_ID, s.GSL_Code, s.Amount }).ToList();
dgvGeneralPoolData.DataSource = Result;
The code works perfectly fine. But when I uncheck the checkbox on datagridview it does not work.
In datagirdview event i have written the following code:
private void dgvGeneralPoolData_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (dgvGeneralPoolData.Rows[e.RowIndex].Cells[0].Selected)
{
Boolean IsChecked = (Boolean) dgvGeneralPoolData.Rows[e.RowIndex].Cells[0].Value;
if (IsChecked)
{
dgvGeneralPoolData.Rows[e.RowIndex].Cells[0].Value = false;
}
}
}
Also, I want to save the changes made in datagridview to the database.
Please help.
EditMode Property
check editmode property of your datagridview.
Does it even hit your click event? Where exactly does it break when you debug? Try to debug and provide some more info if you can.
1) Debug and make sure that the event handler does work. Sometimes when you copy paste the code the event handler doesn't get register by the designer so try deleting the CellClick and type the code again on the grid view, when you add the = sign it should give you an option to create the ClickCell method for you. It should be something like this inside your click event.
if (e.RowIndex != -1)
{
DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell)dgvGeneralPoolData.CurrentRow.Cells["ColumnNumberHere"];
if (chk.Value == null || chk.Value = false)
{
chk.Value = true;
}
else
{
chk.Value = false
}
}
2) Make sure this is under your InitializeComponent()
this.dgvGeneralPoolData.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvGeneralPoolData_CellContentClick);

Popup and ComboBox binding with Silverlight

I have a problem regarding the comportment my ComboBox.
First I use a combobox to display all elements in a IEnumarale.
Then, with a button wich open a popup, the user can add an alement to that list.
The problem is that when the user validate his choice and close the popup, the element is not automatly added to the ComboBox without doing a refresh of the page.
The combobox is coded as follows :
<telerik:RadComboBox x:Name="MyElements"
SelectionChanged="MyElements_OnSelectionChanged"
ItemTemplate="{StaticResource ComboBoxElementsTemplate}"
ItemsSource="{Binding ListElements}"/>
The constructor of the list is :
public IEnumerable<Element> ListElements
{
get { return _listElements; }
set
{
_listElements= value;
RaisePropertyChange("ListElements");
}
}
And the code behind of the button to validate the user choice in the popup :
private ObservableCollection<HistoriqueElement> elementList = null;
private void SelectClick(object sender, RoutedEventArgs e)
{
var element= _GridList.SelectedItem as HistoriquePasserelle;
if (_GridList.SelectedItem != null)
{
var installation = this.DataContext as Installation;
if (installation != null && element!= null)
{
element.DateFin = DateTime.Now;
HistoriqueElement newElement= new HistoriqueElement()
{
Installation = installation,
ContactAction = GlobalActeurs.Current.CurrentContact,
Date = DateTime.Now,
Element = element.Element,
StatutElement = element.StatutElement ,
Owner= element.Owner,
};
elementList.Remove(element);
}
MainPage.ClosePopup();
}
}
When the user choose a new element in the list display in the popup and validate his choice, he returns to the main page, but his choice is not automatically added to the combobox.
I can post you any parts of the code.
Thank you in advance.
The method OnDataContextChanged :
public override void OnDataContextChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is Installation)
{
if (MainPage.CurrentInstallation.LastElements != null)
{
ListElements = MainPage.CurrentInstallation.LastElements;
MyElements.SelectedIndex = 0;
}
else
{
LoadOperation<Element> operation =
_context.Load(_context.GetCurrentElementsByInstallationId(MainPage.CurrentInstallation.Id));
this._busy.IsBusy = true;
operation.Completed += delegate
{
this._busy.IsBusy = false;
if (operation.ManageError())
{
ListElements = operation.Entities;
}
};
}
this.DataContext = this;
}
else
{
RaisePageTitleChanged();
if (MainPage.CurrentInstallation == null)
return;
}
if (MyElements.SelectedItem == null && MyElements.Items.Any())
{
MyElements.SelectedIndex = 0;
}
}
If the collection the ItemsSource is bound to implement INotifyCollection changed, that is, it's an ObservableCollection<>, then the combobox will be notified of any changes to the collection and you will not need to rebind or refresh, it will all be automatic.
Once you add the item to the list, bind the itemsource to the combobox, then you dont have to refersh.
MyElements.ItemsSource = ListElements

How do I give the focus to a TextBox in a DataForm?

I've got a small DataForm and I want to set the focus on the first TextBox. I'm using the Novermber 2009 Toolkit. I've named the TextBox and tried using .Focus() from the DataForm's loaded event. I see it get focus for one cursor 'blink' and then it's gone. I'm trying to work out if this is an artefact of the DataForm or something else. Does anyone know if I should be able to do this?
A little trick I've used successfully is to subscribe to the Loaded event of the textbox, then in the event handler, I set the focus with code such as this:
private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
TextBox usernameBox = (TextBox)sender;
Dispatcher.BeginInvoke(() => { usernameBox.Focus(); });
}
I tried loads of suggestions e.g. using Dispatcher, UpdateLayout etc etc. floating around on various internet sites and none of them worked reliably for me. In the end I settled on the following:
private bool _firstTime = true;
private void MyChildWindow_GotFocus(object sender, RoutedEventArgs e)
{
if (_firstTime)
{
try
{
var dataForm = MyDataForm;
var defaultFocus = dataForm.FindNameInContent("Description") as TextBox;
defaultFocus.Focus();
}
catch (Exception)
{
}
finally
{
_firstTime = false;
}
}
}
Not pretty I know...but it works. There appears to be a timing issue with using the Focus() method in SL4.
Try calling my custom focus setting function (FocusEx).
internal static class ControlExt
{
// Extension for Control
internal static bool FocusEx(this Control control)
{
if (control == null)
return false;
bool success = false;
if (control == FocusManager.GetFocusedElement())
success = true;
else
{
// To get Focus() to work properly, call UpdateLayout() immediately before
control.UpdateLayout();
success = control.Focus();
}
ListBox listBox = control as ListBox;
if (listBox != null)
{
if (listBox.SelectedIndex < 0 && listBox.Items.Count > 0)
listBox.SelectedIndex = 0;
}
return success;
}
}
That should work for you.
Jim McCurdy
YinYangMoney

Winforms DataBind to Control's Visible Property

Are there any known issues when databinding to a control's visible property?
The control is always NOT visible regardless of what my property is.
Public ReadOnly Property IsRibbonCategory() As Boolean
Get
Return True
End Get
End Property
I tried the control's text property and other properties and they seem to work correctly.
I am trying to set a Panel's visible property.
I've found that life is better if you assume that binding to a control's Visible property is broken, despite the fact that it sometimes works. See http://support.microsoft.com/kb/327305, which says as much (and while the KB article applies to .NET 1.0 and 1.1, it still seems to be a problem in at least 2.0).
I created a utility class for creating bindings which, among other things, gave me a centralized place to add a work-around. Instead of actually creating a binding on Visible it does two things:
It subscribes to the data source's INotifyPropertyChanged.PropertyChanged event and sets the Visible value as appropriate when the event is raised.
It sets the initial value of Visible according to the current data source value.
This required a little reflection code, but wasn't too bad. It is critical that you don't bind the Visible property and do the work-around or it won't work.
Workaround: Set the Visible property on the BindingComplete event.
I had same issue setting a label's Visible property - always stays false, even though setting the Enabled property works fine.
I just hit this issue in .NET 4.7.1 and Visual Studio 2017. To fix it, I changed the Visible property on my control to be initially set to True, as I had it as False previously.
Things to check:
Be sure you've instantiated the class that has the IsRibbonCategory property
Did you set the datasource of property of the binding source to the instance of the class
The datasource update mode should be on "on validation"
Make sure you didn't set the visible property manually to false on the control
Hope that helps. Can you post more code?
A workaround would be to use a Component to databind to a control's visiblity property instead of directly binding to the control's visibility property.
See below code:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public class ControlVisibilityBinding : Component
{
private static readonly object EventControlChanged = new object();
private static readonly object EventVisibleChanged = new object();
private System.Windows.Forms.Control _control;
private bool _visible = true;
public event EventHandler VisibleChanged
{
add { Events.AddHandler(EventVisibleChanged, value); }
remove { Events.RemoveHandler(EventVisibleChanged, value); }
}
public event EventHandler ControlChanged
{
add { Events.AddHandler(EventControlChanged, value); }
remove { Events.RemoveHandler(EventControlChanged, value); }
}
public ControlVisibilityBinding()
{
}
public ControlVisibilityBinding(IContainer container)
{
container.Add(this);
}
[DefaultValue(null)]
public System.Windows.Forms.Control Control
{
get { return _control; }
set
{
if(_control == value)
{
return;
}
WireControl(_control, false);
_control = value;
if(_control != null)
{
_control.Visible = _visible;
}
WireControl(_control, true);
OnControlChanged(EventArgs.Empty);
OnVisibleChanged(EventArgs.Empty);
}
}
[DefaultValue(true)]
public bool Visible
{
get { return _visible; }
set
{
if(_visible != value)
{
_visible = value;
}
if(Control != null)
{
Control.Visible = _visible;
}
OnVisibleChanged(EventArgs.Empty);
}
}
private void WireControl(Control control, bool subscribe)
{
if(control == null)
{
return;
}
if(subscribe)
{
control.VisibleChanged += Control_VisibleChanged;
}
else
{
control.VisibleChanged -= Control_VisibleChanged;
}
}
private void Control_VisibleChanged(object sender, EventArgs e)
{
OnVisibleChanged(EventArgs.Empty);
}
protected virtual void OnVisibleChanged(EventArgs e)
{
EventHandler subscribers = (EventHandler)Events[EventVisibleChanged];
if(subscribers != null)
{
subscribers(this, e);
}
}
protected virtual void OnControlChanged(EventArgs e)
{
EventHandler subscribers = (EventHandler)Events[EventControlChanged];
if(subscribers != null)
{
subscribers(this, e);
}
}
}
static class Program
{
[STAThread]
static void Main()
{
using(Form form = new Form())
using(FlowLayoutPanel groupBoxLayoutPanel = new FlowLayoutPanel())
using(RadioButton visibleButton = new RadioButton())
using(RadioButton hiddenButton = new RadioButton())
using(GroupBox groupBox = new GroupBox())
using(Label text = new Label())
using(ControlVisibilityBinding visibilityBinding = new ControlVisibilityBinding())
using(TextBox inputTextBox = new TextBox())
{
groupBoxLayoutPanel.Dock = DockStyle.Fill;
groupBoxLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
groupBoxLayoutPanel.AutoSize = true;
groupBoxLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
visibleButton.Text = "Show Label";
visibleButton.AutoSize = true;
hiddenButton.Text = "Hide Label";
hiddenButton.AutoSize = true;
groupBoxLayoutPanel.Controls.Add(visibleButton);
groupBoxLayoutPanel.Controls.Add(hiddenButton);
inputTextBox.Text = "Enter Label Text Here";
inputTextBox.Dock = DockStyle.Top;
groupBox.AutoSize = true;
groupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
groupBox.Controls.Add(groupBoxLayoutPanel);
groupBox.Dock = DockStyle.Fill;
text.AutoSize = true;
text.ForeColor = Color.Red;
text.Dock = DockStyle.Bottom;
text.BorderStyle = BorderStyle.FixedSingle;
text.Font = new Font(text.Font.FontFamily, text.Font.Size * 1.25f, FontStyle.Bold | FontStyle.Italic);
text.DataBindings.Add("Text", inputTextBox, "Text", true, DataSourceUpdateMode.Never);
visibilityBinding.Control = text;
visibleButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
Binding binding = hiddenButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
ConvertEventHandler invertConverter = (sender, e) => e.Value = !((bool)e.Value);
binding.Format += invertConverter;
binding.Parse += invertConverter;
form.Controls.Add(inputTextBox);
form.Controls.Add(text);
form.Controls.Add(groupBox);
Application.Run(form);
}
}
}
}
Here is my turn around, it may be stupid but it worked many times.
I put one Panel control in my form, I make it to Fill my form and I put everything in that Panel. All the controls I bind the Visible property see their visibility change according to the objects in my DataGridView.

Resources