I'm trying to create a binding from my custom control to objects that are in a BindingList.
While with textbox, I can easily write
textBox.DataBindings.Add("Text",myBindingList,"PropertyOfObjectOfBindingList")
With my custom property "Value", this thing doesn't work (the object doesn't get updated).
What should I implement with my custom control to make it works? I already implemented INotifyPropertyChanged, but it doesn't work.
I just want make this line works:
customControl.DataBindings.Add("CustomProperty",myBindingList,"PropertyOfObjectOfBindingList")
EDIT 1:
I read this around web: http://kbalertz.com/327413/control-using-Visual.aspx however is not working for me at the moment, maybe I'm doing something wrong
Since you said your bound object doesn't get updated (I assume from Control -> Object changes), but it is bound correctly, maybe this will help:
customControl.DataBindings.Add("CustomProperty", list, "BoundObjectProperty",
false, DataSourceUpdateMode.OnPropertyChanged);
Maybe the Implementing complex data binding in custom controls article will help.
I solved the problem by myself:
While the article I linked is a good suggestion, there is a wrong part; you don't have to create an event in your custom class with PropertyChangedEventHandler, but just with EventHandler.
public event EventHandler CustomPropertyChanged;
Is enough to make everything works. Obviusly you have to call it when your property changes
EDIT 1:
I discovered a bad thing, while on textboxes, if the control lose focus the bindinglist get updated, on my custom controls this thing happens only when I change selected item in listbox.
I don't find a way to solve this at the moment.
Related
I'm currently working on a WinForms graphical interface in C#. The form has a ComboBox that is displaying the contents of a custom class I wrote. This class implements the IList interface so that it can be used as the DataSource for that ComboBox.
The issue is that when I add or remove items to/from the underlying object, the ComboBox does not visually reflect this.
I have tried reassigning the list to the DataSource property whenever the contents change, but that doesn't seem to make a difference.
Most of the answers on this site that deal with this issue or similar seem to require a number of extra classes, or editing XAML documents, in order to achieve this.
Is there a simpler method to achieving this? If it makes a difference, the ComboBox will not be visible at the point where changes are made to the IList sourcing it. The only idea I've had so far is to possibly delete the ComboBox and replace it with a new one when needed, but I'm not sure if this is possible to do at runtime, and is obviously not very elegant either way.
I am trying to create a program (simple grid - with specialized output) that displays data from an IBindingList data source. I can display the data just fine, but I also want to be able to let the user edit the data in, say in a TextBox that is separate from the grid. My problem is that I am unclear as to how to accomplish the "automatic" updating of the data between the two elements (my grid and the editable textbox).
The list's ListChanged event, I believe, will tell me when the list itself has changed, but I need the grid to know when the actual data in the list has changed. The only thing I have stumbled upon to tell me when a change external to the grid has occurred is to hook onto the BindingManagerBase.Bindings[0].Parse event. Not that a user would do this, but if the user has established several textboxes that are all bound to the same field, I think I would have to loop through each BindingManagerBase.Binding entry and hook it?
I am presuming I am not doing this correctly, and there is a more generalized way to accomplish this. I would GREATLY appreciate some direction from anyone who is more familiar with what I am attempting to accomplish.
Thanks in advance,
-Matt
Have a look at at INotifyPropertyChanged. Implement it on the class that is stored in your BindingList to notify said BindingList when properties on an item change.
If you've implemented IBindingList yourself you'll need to do a little more work to hook up to the events for each item in your list, but the provided BindingList will pick up on these events automatically.
You could also use the generic BindingList and notify the edit using ResetItem
I have a form with a programmatic property called SelectedAccessGroups:
[Bindable(true)]
public string SelectedAccessGroups
{
get { return "Selected Access Groups here"; }
}
I also have a BindingSource on the form which has a field called EditableByAccessGroups. I would like to bind my SelectedAccessGroups property to that field.
I attempted the following in my form's constructor, but it doesn't work:
this.DataBindings.Add(new System.Windows.Forms.Binding("SelectedAccessGroups",
this.CriteriaBindingSource, "EditableByAccessGroups"));
Is there a way to accomplish this?
Thanks!
Update: The error I was getting when attempting to run my program was quite undescriptive, but looking into it further, I found that I was getting the error because my property was read-only. I added a blank setter to the property, and the binding works fine now.
You have to implement INotifyPropertyChanged on your class so the bound items will know when something is different. here is an msdn article and there are several other articles out there that will help as well in implementing this interface.
http://msdn.microsoft.com/en-us/library/ms743695.aspx
Per your update and change of the question, to get one-way binding you could use use one of the other Binding constructors that takes DataSourceUpdateMode as a parameter.
http://msdn.microsoft.com/en-us/library/system.windows.forms.binding.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.datasourceupdatemode.aspx
Rather than add the cruft of a blank setter, try using the overloaded constructor of Binding that takes a DataSourceUpdateMode value and passing DatasourceUpdateMode.Never. This will prevent the binding from attempting to update the datasource from the control.
I've been looking into MVVM lately, and after I discovered Caliburn.Micro things have been pretty swell; I'm still in the early learning stages, but I belive I have an OK feel for the MVVM basics.
I'm bumping into issues with WPF DataGrid, though - and it's pretty much the same issues that I had with WinForms DataGridView: how the heck do you handle CanUserAddRows=true in-grid item adding cleanly?
I obviously don't want to add DataGrid-specific hacks to my ViewModel, since it ideally should be repurposable for other View controls. At the same time, I'd like to be able to get a notification when a new row item has been added, so I can persist it right away.
I'm binding the DataGrid to a BindableCollection<FooModel> FooItems - with a clean MVVM design, if I understand things correctly, I would be able to handle FooItems.CollectionChanged and react to Add/Remove events. However, the DataGrid fires the Add event as soon as a default-constructed item is added - this is obviously not the right time to persist the object!
After a lot of googling and digging through StackOverflow, I'm getting the impression that DataGrid is being utterly retarded in how it's firing the Add/Remove events. People who use it with CanUserAddRows=true seem to only work on in-memory collections, where people who persist data seem to use separate input fields + buttons Commands to add new items.
My FooModel implements INotifyPropertyChanged but not IEditableObject - as far as I can tell that shouldn't be the problem, though, since IEO seems related to property edit/undo, whereas my problem is with when the Add event is fired...
So, what do you do to handle in-grid editing cleanly?
It sounds like the WPF DataGrid behaves in much the same way as the WinForms DataGridView, in that it creates an item in the data source as soon as the user begins entering into the 'new row'. Subsequent edits would result in changes to the properties of the new item in the collection.
If you were to use BindingList<FooModel> instead, you get the additional event called ListChanged - providing your FooModel type implements INotifyPropertyChanged, the event will fire when the properties of the item are changed (as well as when items are added/removed from the collection).
Hope this helps!
I know it's been a long time since this was asked but I'm working on something similar now and thought I'd post my solution. You may consider this a hack but it's the best way I could figure to get DataGrid to tell me when it was out of edit mode (for my own reasons).
I looked through the DataGrid code and found the closest thing to end edit I could override, which turns out to be OnExecutedCommitEdit(). I then just raise an event after that function finishes. When my event subscriber gets called DataGrid is no longer in edit mode and I can do whatever I need to it. Here's the code:
/// <summary>
/// Deriving a new DataGrid because we need an event to tell us when editing is complete.
/// </summary>
public class DataGridMod : DataGrid
{
public delegate void EditCompletedDelegate();
public EditCompletedDelegate EditCompleted;
public DataGridMod() { }
protected override void OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
{
base.OnExecutedCommitEdit(e);
if (EditCompleted != null)
EditCompleted();
}
}
How is data binding in C# WinForms supposed to work when you have a Save button? I don't want the data updated until I press Save!
I have two forms (list and detail) backed by a BindingList<T> collection and my custom object from that collection, respectively. I can bind each form to the list or object appropriately. However, any changes made in the detail form are immediately reflected in the list form - I don't want to save the changes and update the details shown in the list until the Save button is pressed.
Is data binding designed to support this? Is there a common pattern for doing so?
Whichever way I look at it, binding doesn't seem to be able to support this scenario. I've considered the following:
Pass a clone of the object to the detail form, but then I have to reconcile the changes on Save - changes may have been made to the copy in the list in the meantime.
Implementing IEditableObject and calling EndEdit on save almost works as I can prevent the list being notified of the changes made until Save is pressed, but if something else causes a refresh the list is updated with the interim data.
I'm currently left with dispensing with data binding in my detail view, and doing it all manually. Which is rather annoying.
Data binding really wasn't designed for this kind of thing, unfortunately.
The best solution we've found here is to edit object clones, then reconcile the changes, as you mentioned. You may want to come up with a custom collection and/or object interface that helps you manage this type of thing.
Even if the cloning method is slightly more work up front, it's going to be wayyyy less complicated and frustrating than using IEditableObject trying to catch all the possible events that update the data. Not only that, it's a more straightforward approach, and you won't end up with spaghetti code.
If you are set on using a binding list, your best bet would be to implement IBindingList to create the functionality that you desire. It may also be possible to pull this off by simply inheriting from BindingList and overriding the appropriate methods to change the binding list's behavior.
http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.aspx
If you are not set on using a binding list, it is probably best to do the data manipulations manually based off of the control's events.
Best of luck.