ToolStripComboBox.SelectedItem change does not propagate to binding source - c#

My binding is set up as this:
_selectXAxisUnitViewModelBindingSource = new BindingSource();
_selectXAxisUnitViewModelBindingSource.DataSource = typeof(SelectXAxisUnitViewModel);
_selectedUnitComboBoxBindingSource = new BindingSource();
_selectedUnitComboBoxBindingSource.DataSource = _selectXAxisUnitViewModelBindingSource;
_selectedUnitComboBoxBindingSource.DataMember = "AvailableUnits";
_selectedUnitComboBox.ComboBox.DataSource = _selectedUnitComboBoxBindingSource;
_selectedUnitComboBox.ComboBox.DisplayMember = String.Empty;
_selectedUnitComboBox.ComboBox.ValueMember = String.Empty;
_selectedUnitComboBox.ComboBox.DataBindings.Add("SelectedItem",
_selectXAxisUnitViewModelBindingSource,
"SelectedUnit", true, DataSourceUpdateMode.OnPropertyChanged);
// this is a bug in the .Net framework: http://connect.microsoft.com/VisualStudio/feedback/details/473777/toolstripcombobox-nested-on-toolstripdropdownbutton-not-getting-bindingcontext
_selectedUnitComboBox.ComboBox.BindingContext = this.BindingContext;
The property "AvailableUnits" is a collection of strings and the "SelectedUnit" is a string-property. Now the dropdown list is populated as expected, but when I select and item in the list, the change is not propagated to the binding source. Any idea what I am doing wrong?
Update:
I Created a little test project and this problem occurs when I add a ToolStripComboBox as a subitem of another ToolStripItem. If I add the ToolStripItem directly to the MenuStrip everything works fine. The BindingContext is not assigned to the ToolStripComboBox when added as a sub item (see my code-comment) and my fix doesn't seem to do whats necessary to get this to work.

Can you change
_selectXAxisUnitViewModelBindingSource.DataSource = typeof(SelectXAxisUnitViewModel);
To
_selectXAxisUnitViewModelBindingSource.DataSource = new SelectXAxisUnitViewModel();

Related

Programmatically create a checkbox binding for a WPF form

I need to programmatically create a binding for a checkbox that resides in a WPF form. Because the checkbox is in a user control that gets added to the form multiple times, I'm unsure how to do this. I've created a binding for a DevExpress RichEdit control which worked and then modified that code for the checkbox, but it didn't work.
My code to return the binding is as follows:
private Binding SetIsCorrectBinding(int row)
{
Binding binding = new Binding("DataModel.DetailList[" + row + "].IsCorrect")
{
Path = new PropertyPath("DataModel.DetailList[" + row + "].IsCorrect"),
Mode = BindingMode.TwoWay
};
return binding;
}
The code to implement the binding is as follows:
Binding cbBind = SetIsCorrectBinding(row);
detailRow.IsCorrect_cb.SetBinding(CheckBox.ContentProperty, cbBind);
No matter what I try, the IsCorrect variable is always false.
Any help with this would be greatly appreciated.
Please try the next:
var xBinding = new Binding();
//a real instance of the object where the source property is defined
//it have to be the same instance which is defined in DataModel.DetailList
xBinding.Source = sourceInstance;
xBinding.Path = new PropertyPath("The_source_property_name");
xBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
xBinding.Mode = BindingMode.TwoWay;
//Use this instead the .SetBinding( , ) where the checkbox is the object to binded to
BindingOperations.SetBinding(checkbox, CheckBox.ContentProperty, xBinding);
Please look at the next solution here, I think it can supply an additional information for you.
I will glad to help if you will have the problem with code.
regards,
6 years late, but I had a similar issue. You need to bind to the Checkbox.IsCheckedProperty
detailRow.IsCorrect_cb.SetBinding(CheckBox.IsCheckedProperty, cbBind);
was the fix you needed.

Winforms Databinding Combobox reverting on lostfocus

I have an Employee object that has an EmploymentStatusID (int) field.
I have a combobox that is filled from an Employment Status enum and bound to the field in the Form_Load:
List<LookupListItem> EmpStatuses = new List<LookupListItem>();
foreach (EmploymentStatuses m in Enum.GetValues(typeof(EmploymentStatuses)))
{
EmpStatuses.Add(new LookupListItem((int)m, m.ToString()));
}
cboStatus.DataSource = EmpStatuses; // Enum.GetValues(typeof(CommonLibrary.Lookups.EmploymentStatuses));
cboStatus.ValueMember = "ItemValue";
cboStatus.DisplayMember = "ItemDesc";
cboStatus.DataBindings.Add("SelectedValue", _presenter.SelectedOfficer, "EmploymentStatusID");
When the form comes up the correct value is displayed in the combobox, but if the user changes the value, it is set back when the combobox loses focus!
Text boxes and simple comboboxes (ie ones with a string collection) on the same form are fine.
You can see that I originally tried just using GetValues on the enum, but I changed it to a list to see if that would help. I've tried using a BindingList, I've tried using DataSourceUpdateMode.OnValidation on the binding. I even tried using cboStatus.DataBindings[0].WriteValue on the selectedindexchanged event. No matter what I do, the value changes back to what it was when the form opened! Any ideas?
i modified your code
List<LookupListItem> EmpStatuses = new List<LookupListItem>();
foreach (EmploymentStatuses m in Enum.GetValues(typeof(EmploymentStatuses)))
{
EmpStatuses.Add(new LookupListItem((int)m, m.ToString()));
}
EmpStatuses.Add(new LookupListItem(<selectedValue>, "SomeText")); //<- my modified code
cboStatus.DataSource = EmpStatuses; // Enum.GetValues(typeof(CommonLibrary.Lookups.EmploymentStatuses));
cboStatus.ValueMember = "ItemValue";
cboStatus.DisplayMember = "ItemDesc";
// Remove this part cboStatus.DataBindings.Add("SelectedValue", _presenter.SelectedOfficer, "EmploymentStatusID");
cboStatus.SelectedValue = <selectedValue> //<- my modified code
i hope this will help :)

Trying to Bind List<T> to CheckedListBox in WinForms c#

I am using WinForms C#
Is there any way to get following behavior:
bind List to CheckedListBox
When I add elements to list CheckedList box refereshes
When I change CheckedListBox the list changes
I tried to do the following:
Constructor code:
checkedlistBox1.DataSource = a;
checkedlistBox1.DisplayMember = "Name";
checkedlistBox1.ValueMember = "Name";
Field:
List<Binder> a = new List<Binder> { new Binder { Name = "A" } };
On button1 click:
private void butto1_Click(object sender, EventArgs e)
{
a.Add(new Binder{Name = "B"});
checkedListBox1.Invalidate();
checkedListBox1.Update();
}
But the view does not update .
Thank You.
Change this line:
List<Binder> a = new List<Binder> { new Binder { Name = "A" } };
to this:
BindingList<Binder> a = new BindingList<Binder> { new Binder { Name = "A" } };
It will just work without any other changes.
The key is that BindingList<T> implements IBindingList, which will notify the control when the list changes. This allows the CheckedListBox control to update its state. This is two-way data binding.
Also, you could change these two lines:
checkedListBox1.Invalidate();
checkedListBox1.Update();
to this (more readable and essentially does the same thing):
checkedListBox1.Refresh();
Two things you may wish to look at:
Use a BindingList
Add a BindableAttribute to your Name property
Does your List<Bender> need to be some kind of observable collection, like ObservableCollection<Bender> instead?
The proper way of binding a checked listbox is:
List<YourType> data = new List<YourType>();
checkedListBox1.DataSource = new BindingList<YourType>(data);
checkedListBox1.DisplayMember = nameof(YourType.Name);
checkedListBox1.ValueMember = nameof(YourType.ID);
Note to self.
The issue i have every time binding it is that the properties DataSource, DisplayMember and ValueMember are not suggested by intellisense and i get confused.

How to properly bind to a child object?

I have an object Proposal which has a property called CurrentAgency of Agency which in turn has AgencyID, Name, etc...something like this:
Proposal
CurrentAgency
AgencyID
Name
Address
etc...
In my UI, I have a combobox that lists all available Agencies. I have bound it like this:
private BindingSource bndProposal = new BindingSource();
bndProposal.DataSource = typeof(Model.Proposal);
lkpAgency.DataBindings.Add("EditValue", bndProposal, "CurrentAgency.AgencyID");
lkpAgency.Properties.DataSource = FusionLookups.LookupAgencies;
lkpAgency.Properties.DisplayMember = "Name";
lkpAgency.Properties.ValueMember = "ID";
And this works well enough. If the user changes the agency, Proposal.CurrentAgency.AgencyID is automatically updated. However, the problem is that the rest of the properties of the CurrentAgency object are not updated.
What are some of the patterns that are used to handle this kind of situation while not gunking up the code with junk? Do I handing the Format event on the Binding object? Any ideas for clean implementation are welcome.
Have you tried the following?
private BindingSource bndProposal = new BindingSource();
bndProposal.DataSource = typeof(Model.Proposal);
lkpAgency.DataBindings.Add("EditValue", bndProposal, "CurrentAgency");
lkpAgency.Properties.DataSource = FusionLookups.LookupAgencies;
lkpAgency.Properties.DisplayMember = "Name";
lkpAgency.Properties.ValueMember = null;

unable to edit DataGridView populated with results of LINQ query

When i use the results of a linq-to-xml query to populate a datagridview, i cannot edit the datagridview. i've tried setting the datagridview's readonly property to false and that doesn't help. I also added an event handler for cellBeginEdit and put a breakpoint there, but it doesn't get hit. Any idea what i'm doing wrong, or if this isn't possible?
public class MergeEntry
{
public string author { get; set; }
public string message { get; set; }
}
...
var query = from entry in xmlDoc.Descendants("entry")
select new MergeEntry
{
author = entry.Element("author").Value,
message = entry.Element("msg").Value,
}
var queryAsList = query.ToList();
myBindingSource.DataSource = queryAsList;
myDataGridView.DataSource = myBindingSource;
Yes, it is possible to bind to a list created from Linq-To-Xml. I tried to reproduce your problem. I did the following:
Created an empty WindForm project (VS 2008 and .Net 3.5)
Added a DataGridView to the Form.
Wired the CellBeginEdit and CellEndEdit.
Placed the following code in the Form's constructor
string testXML =
#"<p><entry>
<author>TestAuthor1</author>
<msg>TestMsg1</msg>
</entry></p>
";
XElement xmlDoc = XElement.Parse(testXML);
var query = from entry in xmlDoc.Descendants("entry")
select new MergeEntry
{
author = entry.Element("author").Value,
message = entry.Element("msg").Value,
}; //You were missing the ";" in your post, I am assuming that was a typo.
//I first binded to a List, that worked fine. I then changed it to use a BindingList
//to support two-way binding.
var queryAsList = new BindingList<MergeEntry>(query.ToList());
bindingSource1.DataSource = queryAsList;
dataGridView1.DataSource = bindingSource1;
When running the WinForm app, an editable grid was displayed and the CellBeginEdit and CellEndEdit events were fired when they should have been. Hopefully trying to reproduce using the above steps will help you locate the issue you are facing.
Since you're using ToList, your DataSource is actually a List<MergeEntry>, so the fact that it comes from a Linq query doesn't change anything. I suspect the ReadOnly property of the columns (not the DGV) is set to true... I see no other reason why the grid wouldn't be editable
This solution may not efficient but it works for me,
I moved all data (which is from LINQ) into a new collection and passed that new collection as datasource to gridview.
Now gridview allow us to edit cells.

Categories