I need to make list of items. I binded collection of users to listbox. Everything works quite well, but items in listbox aren't updated in real time. They aren't updated at all by this binding. So when I remove any user from the list, listbox isn't updated even if its source is correctly changed.
Source is located in data view model at path DataViewModel.Instance.AllUsers; Whenever I add to this list new item or remove one, layout does not update. Other bindings work well. I tried to update listbox layout, to raise event of source update, other way of adding/removing items, but nothing worked.
I tried to debug binding, but I have too many bindings to find the error.
Thanks in advance for any useful advice.
Listbox:
<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/>
Code-behind:
CatalogueGrid.DataContext = DataViewModel.Instance; //whole view model added as datacontext
DataViewModel class:
public class DataViewModel : INotifyPropertyChanged
{
private static DataViewModel _dataViewModel;
private Collection<UserModel> allUsers;
public Collection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
private DataViewModel()
{
AllUsers = new Collection<UserModel>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(info));
}
}
.
.
.
}
use ObservableColLection instead if Collection wich implements the INotifyCollectionChanged Interface :
private ObservableCollection<UserModel> allUsers;
public ObservableCollection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
For changes to the collection to propagate to the UI, the collection class needs to implement INotifyCollectionChanged.
A very useful class that already implements this is ObservableCollection<T> (MSDN). Use that instead of Collection<T>.
You have bound your listbox to a Collection<T> - that is just a list, which does not issue any notifications to bound properties that its contents has changed. Hence, your listbox cannot possibly know when the collection has changed.
Instead, you can use the ObservableCollection<T> class (or, more precisely, any collection that also implements INotifyCollectionChanged), and changes will be automatically propagated to the listbox.
Note that your property does not have to be typed as ObservableCollection<T>, you can also just declare your public property as IEnumerable<T> or IList<T>; the binding will find out on its own whether the returned class also implements INotifyCollectionChanged. Like this, you are free to replace your actual underlying collection class later on, for example with a ReadOnlyObservableCollection<T>, in case you want to disallow changes from the outside.
Speaking of this, a note on your code: You have provided your AllUsers property with a setter. This may lead to undesired consequences, as you open up possibilities for some other code to set the property to null, which (depending on the rest of your code) might lead to exceptions. Unless you actually want to allow assigning new values, for the ItemsSource property binding, a read-only property is fully sufficient, as long as the returned collection object implements INotifyCollectionChanged.
Related
I have a Listbox with a DataTemplate which includes a Combobox. I need to change the selectedItem/Index of a particular ComboBox. How would I access it?
Additional Detail
All the combobox have the same options. If a Combobox is set to the same value as another ComboBox then the Combobox that was set first should return to empty (which is the first item in my cbxOptions Dictionary that the ComboBoxes are Bound to).
<DataTemplate x:Key="lbxHeaderDataTemplate">
<Grid>
<Label Content="{Binding Item1}"></Label>
<ComboBox Grid.Column="1" ItemsSource="{Binding Item2}"
DisplayMemberPath="Key" SelectionChanged="ComboBox_SelectionChanged"></ComboBox>
</Grid>
</DataTemplate>
C#
Populate UI
foreach (DataColumn dc in _loadedData.Columns)
{
ListBox.Items.Add(new Tuple<string, Dictionary<string, string>>
(dc.ColumnName, cbxOptions));
}
Trying to wipe combobox
This is where I would expect I could foreach through the Listbox, checking the controls for a match at which point I'd change it to blank. However my foreach just gives me back stupid Tuple...which is readonly but I don't think that'd update my ComboBox anyways.
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox cbxSelected = (ComboBox)sender;
DependencyObject parent = VisualTreeHelper.GetParent(cbxSelected);
Label currentLbl = null;
foreach (object o in ((Grid)parent).Children)
{
if (o is Label)
{
currentLbl = (Label)o;
}
}
string LblText = currentLbl.Content.ToString();
string cbxValue = cbxSelected.SelectedValue.ToString();
//HERE I want to iterate through the listbox controls, not the datasource
foreach (Tuple<string, Dictionary<string, string>> l in lbxDatFields.Items)
{
//l.Item2 = "";
if (l.Item1.EndsWith(cbxOptions[cbxValue]))
l = new Tuple<string, Dictionary<string, string>>(l.Item1, "");
}
}
I'm sure there must be a very simple way of accessing the control. Any help would be much appreciated. Please let me know if additional info is required.
Without a good Minimal, Complete, and Verifiable code example that clearly and concisely illustrates your question, it's not practical to try to address your current design. Based on the bit of code you did post, one can make some observations though:
Since Tuple<...> is immutable, you can't modify the Item2 property. You have to replace the entire Tuple<...> object with a new one.
The code you posted shouldn't even compile, because you are trying to modify the l variable in the foreach loop.
Even if you could, it wouldn't change the element in the list itself, just that particular variable.
Not that you even want to change the element; it's the selection of the combo box that should change, not its Item2 options.
The use of a dictionary object for the ComboBox items eludes me. Perhaps with a complete code example, it would be more clear.
All that said…
How would I access it?
This question comes up only because you are misusing WPF to start with. You should not be manipulating the UI directly; instead, your UI state should be represented in view model data structures. Then the ComboBox selection would be bound to a view model property, and the answer to your question would be simply to look at that property.
It's hard to know for sure, given the lack of details, but it appears to me that you are trying to implement a scenario where you have a list of items, where each item has a selectable option, and you want those options to be mutually exclusive. That is, only one item at a time can have any given option.
Assuming that's the case, I will show an implementation that in my opinion is much better than the approach you are attempting to implement. That is, it uses the basic idea I've proposed above, where you start with the data models, and then work back to the UI from there. Doing it this way, the data models are very simple and easy to understand, and so is all of the implementation for the behavior you want.
It looks like this…
First, start with the basic per-item view model data structure:
class PropertyChangedExEventArgs<T> : PropertyChangedEventArgs
{
public T OldValue { get; }
public PropertyChangedExEventArgs(string propertyName, T oldValue)
: base(propertyName)
{
OldValue = oldValue;
}
}
class ItemViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { _UpdateField(ref _name, value); }
}
private string _value;
public string Value
{
get { return _value; }
set { _UpdateField(ref _value, value); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void _UpdateField<T>(ref T field, T newValue,
Action<T> onChangedCallback = null,
[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return;
}
T oldValue = field;
field = newValue;
onChangedCallback?.Invoke(oldValue);
PropertyChanged?.Invoke(this,
new PropertyChangedExEventArgs<T>(propertyName, oldValue));
}
}
Notes:
The above class implements INotifyPropertyChanged directly. In a real-world program, this implementation would typically be in a base class, which each view model class inherits. If you do a significant amount of WPF programming, you'll have this base class as a reusable component you just include in each project, either in a separate project you reference, or as a code snippet. There are many WPF user frameworks you can use as well, which provide this functionality.
In this particular example, there's not already a convenient mechanism for event subscribers to know the old value of the property after it's changed, but the logic involved requires that, so that the key for the mapping from value to model object can be removed from the dictionary when it's no longer valid. There are a variety of ways to address that need — arguably, the more straightforward is to just do a linear search of the Values collection of the relatively small dictionary. But I decided to extend the PropertyChangedEventArgs class instead, as that's a more scalable solution to that particular need (and so is more useful as a general solution to the problem).
Here, I only need one class to implement that interface, and it's simpler for the sake of illustration to keep everything together there.
Okay, so with the per-item data structure in place, we also want a parent data structure to encapsulate these items as a collection and to handle the broader manipulation of these items:
class MainViewModel
{
public ObservableCollection<ItemViewModel> Items { get; } =
new ObservableCollection<ItemViewModel>
{
new ItemViewModel { Name = "Item #1" },
new ItemViewModel { Name = "Item #2" },
new ItemViewModel { Name = "Item #3" },
};
public IReadOnlyList<string> Options { get; } =
new [] { "Option One", "Option Two", "Option Three" };
private readonly Dictionary<string, ItemViewModel> _valueToModel =
new Dictionary<string, ItemViewModel>();
public MainViewModel()
{
foreach (ItemViewModel itemModel in Items)
{
itemModel.PropertyChanged += _ItemPropertyChanged;
}
}
private void _ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ItemViewModel.Value))
{
ItemViewModel itemModel = (ItemViewModel)sender;
PropertyChangedExEventArgs<string> exArgs =
(PropertyChangedExEventArgs<string>)e;
if (exArgs.OldValue != null)
{
_valueToModel.Remove(exArgs.OldValue);
}
if (itemModel.Value != null)
{
if (_valueToModel.TryGetValue(
itemModel.Value, out ItemViewModel otherModel))
{
otherModel.Value = null;
}
_valueToModel[itemModel.Value] = itemModel;
}
}
}
}
This object maintains the collection of items, as well as the collection of options for the ComboBox elements. This is also where the logic to handle the mutual-exclusion of options is handled, because this is the class that has access to all of the per-item data objects.
On that last point: you could, of course, provide a way for the per-item objects to interact with the parent data structure to be able to enumerate the other per-item objects. This would allow each per-item object to handle its own property changes, so that the parent object doesn't need to subscribe to each per-item object's PropertyChanged event. But doing so would also increase coupling between the classes and make the basic logic harder to follow. IMHO, it is preferable to keep this top-down approach, where owned objects know as little as possible about their owners (and in this case, nothing at all).
Note that with the above, all of the logic necessary to track the state of the items and ensure mutual exclusion of the options setting is present, without anything that is actually specific to the view objects. The above code would work in any program, with or without a user interface. It's completely decoupled from the view itself.
And so, how does the view use it? Like this:
<Window x:Class="TestSO45196940ComboBoxExclusive.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:l="clr-namespace:TestSO45196940ComboBoxExclusive"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:MainViewModel/>
</Window.DataContext>
<StackPanel>
<ListBox ItemsSource="{Binding Items}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type l:ItemViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Name}"/>
<ComboBox ItemsSource="{Binding DataContext.Options, RelativeSource={RelativeSource AncestorType=ListBox}}"
SelectedItem="{Binding Value}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.Resources>
</ListBox>
</StackPanel>
</Window>
Similar to how the ItemViewModel object knows nothing about the MainViewModel, but rather the latter subscribes to the former's PropertyChanged event and accesses the item object's properties to do the work, the view binds to the relevant properties of both model objects, without those objects having any need to know about those bindings, or the view itself.
The view has no code-behind at all. It's just a simple, declarative description of what the user sees, and does nothing more than present to the user the current state of the underlying data.
Doing it this way keeps everything very simple and disconnected, so that each object has a very narrow set of responsibilities, and the interaction between objects is kept to a minimum. This makes it easier to assure that the code is correct, and reduces the mental workload when implementing features, because you're only dealing with a small section of the code at a time, instead of having to keep straight how everything relates to each other.
For what it's worth, it took way longer to explain the code above here in this post, than it did to write the code itself. Following the standard WPF idioms, the actual authoring the code can go very quickly, especially if you already have the basic base classes in place for things like INotifyPropertyChanged. Much of that time savings comes from not having to puzzle over how to get at the data you need. By following better practices, the data is always already right there where you want it.
I have a Listbox with a DataTemplate which includes a Combobox. I need to change the selectedItem/Index of a particular ComboBox. How would I access it?
By accessing the corresponding data item in the Items collection of the ListBox.
Replace your Tuple<string, Dictionary<string, string>> with a class that also includes a SelectedIndex property. Make sure that you implement the INotifyPropertyChanged interface correctly:
class DataItem : INotifyPropertyChanged
{
public string Item1 { get; set; }
public Dictionary<string, string> Item2 { get; set; }
private int _selectedIndex;
public int SelectedIndex
{
get { return _selectedIndex; }
set { _selectedIndex = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
...
foreach (DataColumn dc in _loadedData.Columns)
{
ListBox.Items.Add(new DataItem() { Item1 = dc.ColumnName, Item2 = cbxOptions });
}
Then you bind the SelectedIndex property of the ComboBox in your DataTemplate to your SelectedIndex property:
<ComboBox Grid.Column="1" ItemsSource="{Binding Item2}" DisplayMemberPath="Key"
SelectedIndex="{Binding SelectedIndex}"></ComboBox>
And change the selected index of a ComboBox by setting the source property of the corresponding object in the Items collection:
(ListBox.Items[2] as DataItem).SelectedIndex = 1;
When I'm binding, say a Label to a string, I define the string this way:
private string _lbl;
public string Lbl
{
get
{
return = _lbl;
}
set
{
_lbl=value;
OnPropertyChanged("Lbl");
}
}
With the INotifyPropertyChanged interface implemented in my class.
Should I define the same way an ObservableCollection or I just could leave it this way?
public ObservableCollection<File> myFiles {get; set;}
As a general rule, I tend to define ObservableCollections like this:
private ObservableCollection<Item> _items;
public ObservableCollection<Item> Items
{
get { return _items ?? (_items = new ObservableCollection<Item>()); }
}
This is called "Lazy initialization", where the ObservableCollection is only instantiated where it is first accessed.
This is a good way to ensure your Collection Will Never Be Null
Notice that it does not have a setter, because an ObservableCollection is not something that you usually assign to. Instead, if you want to completely replace items, do:
Items.Clear();
//... Add all the new items
This avoids WPF having to rebind all the CollectionChanged events and stuff in order to listen to and react to items added / removed from the collection. You only have 1 instance of the collection, forever. Whatever items you place on it, the collection remains the same.
This is not to be confused with the PropertyChange notification inside the ITEMS of the collection. WPF handles these concepts separately, because property changes are notified by ITEMS, but Collection changes (Item added or removed) are notified by the Collection itself.
If the myFiles property can change, then yes, you should raise the PropertyChanged event. If not (that is, if it's got no setter, or it has a private setter that is only set once, e.g. in the constructor), then you don't need to raise the event. The collection itself will raise its own PropertyChanged and CollectionChanged events, but the object that contains the collection must raise PropertyChanged if the property that contains the collection changes.
I can't seem to figure this out and couldn't find any answers.
I have a Combobox binded to a property in my model.
I'll just copy and paste key lines in my code:
this.m_typeCombobox.DataBindings.Add(new System.Windows.Forms.Binding("EditValue", this.m_bindingSource, "Type", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
My Model:
public class TypeConfig : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private EnumType<eLType> m_type;
public EnumType<eLType> Type
{
get { return m_type; }
set
{
if (m_type!= value)
{
m_type= value;
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("Type"));
}
}
}
I need to have the model updated on combobox EditValueChanged event but it looks like the model is updated later. EditValueChanged is the latest called event when changing.
I have tried this:
void m_TypeCombobox_EditValueChanged(object sender, EventArgs e)
{
m_bindingSource.EndEdit(); //this doesn't work
//need to have the new value here
}
Here's what MSDN says:
When the EndEdit method is called, all pending changes are applied to the underlying data source.
This method has no effect unless the objects contained by the data source implement the IEditableObject interface. If the objects do not implement the IEditableObject interface, changes to the data are copied to the underlying data source immediately after each change.
So, from my undesrstanding the model should be immediately updated when changing the combobox value.
I'm using a DevExpress combobox that's pretty much the same as a normal WinForms combobox.
How can i workaround this?
try to make binding to "Value" property, rather than "EditValue"
I hope it helps you
For BindingSource.EndEdit to do anything, You need to implement System.ComponentModel.IEditableObject for the items contained within the BindingSource.
When you invoke "EndEdit" on the binding source, it subsequently invokes the corresponding IEditableObject.EndEdit() method on the items in it's list that implement IEditableObject.
Having said that, I am having some issues with EndEdit not being called for all items that BeginEdit has been called on when, eg, the user closes the form.
I try to "filter" an ObservableCollection and update the bound DataGrid.
ObservableCollection<Record> recordObservableCollection;
recordObservableCollection = new ObservableCollection<Record>(GetData()); //GetData() returns IEnumerable<Record>
dataGrid1.ItemsSource = recordObservableCollection;
Then I try to filter this collection:
recordObservableCollection = new ObservableCollection<Record>(recordObservableCollection.Where(filter));//filter is Func<Data.Record, bool>
recordObservableCollection is updated fine.
But the DataGrid is not updated.
Your field or variable called recordObservableCollection has one value initially and a different value after filtering. Because you used new ObservableCollection<Record>(...) twice you created two separate observable collection instances.
The problem is that the DataGrid is still referring to the first instance. Even though you have changed recordObservableCollection, that only affects its value. The value of DataGrid.ItemsSource is still what it was before the filtering.
To fix this problem, you need to re-assign the new collection's value to the ItemSource property. Simply repeat what you did the first time, but after the filtering:
dataGrid1.ItemsSource = recordObservableCollection;
and now ItemSource will be set to the new value of recordObservableCollection.
ObservableCollection will get update because ObservableCollection (System.Collections.ObjectModel) throws an event every time the collection get changed but you have to set the filter collection as itemsource again other wise it wont update the UI...
The best way to do this use a public property that you'll bind in control as item source and in that property you will define NotifyPropertyChanged in setter . Every time you'll change the collection using this property the control will also be updated ...
Let Suppose you have your data grid in test.xaml
--> First fo all work for INotifyPropertyChanged add an abstract class in your project inherit it from INotifyPropertyChanged interface and define OnPropertyChanged method
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
--> After add a class in your project named it testViewModel which will inherit your ViewModelBase Class..
--> Now in testViewModel you'll make a property for your grid binding like this
Private ObservableCollection<Record> _recordObservableCollection
public ObservableCollection<Record> recordObservableCollection
{
get
{
if(_recordObservableCollection == null)
{
_recordObservableCollection = new ObservableCollection<Record>(GetData());
recordObservableCollection = new ObservableCollection<Record>(recordObservableCollection.Where(filter));
}
return _recordObservableCollection;
}
Set
{
_recordObservableCollection = Value;
OnPropertyChanged("recordObservableCollection"); //Your property name
}
}
here now if u update your collection using property on any other property, method or command UI will be updated beacsue in setter you have defined OnPropertyChanged...
Now comes back to test.xaml here you have to do two things
Set dataContext of test.xaml either in code behing or in in xaml
(In Code behind just after InitializeComponent() make an intance of viewmodel class and assign it as DataContext like this
public test()
{
InitializeComponent();
testViewModel vm = new testViewModel();
this.DataContext = vm;
}
Bind property you defined in testViewModel to grid
<Grid Name="MyGrid" DataContext="{Binding recordObservableCollection}">
</Grid>
Expose the ObservableCollection<Record> as a public property
also
Using ObservableCollection only affect binding when you add/remove items from your list. By using ObservableCollection you do not need to reset binding to the list or DataGrid when your collection changed (not the item inside collection changed). But they do not have any effect when your data object properties changed. For that you need to implement INotifyPropertyChanged interface for your DataObject.
I have a simple usercontrol (WinForms) with some public properties. When I use this control, I want to databind to those properties with the DataSourceUpdateMode set to OnPropertyChanged. The datasource is a class which implements INotifyPropertyChanged.
I'm aware of the need to create bindings against the properties and I'm doing that.
I assumed that my usercontrol would have to implement an interface, or the properties would need to be decorated with some attribute, or something along those lines.But my research has come up blank.
How should this be accomplished? At the moment I'm doing it by calling OnValidating() in my usercontrol whenever a property changes, but that doesn't seem right.
I can get validation to happen if I set the CausesValidation to true on the usercontrol, but that's not very useful to me. I need to validate each child property as it changes.
Note this is a WinForms situation.
EDIT: Evidently I have no talent for explanation so hopefully this will clarify what I'm doing. This is an abbreviated example:
// I have a user control
public class MyControl : UserControl
{
// I'm binding to this property
public string ControlProperty { get; set; }
public void DoSomething()
{
// when the property value changes, the change should immediately be applied
// to the bound datasource
ControlProperty = "new value";
// This is how I make it work, but it seems wrong
OnValidating();
}
}
// the class being bound to the usercontrol
public class MyDataSource : INotifyPropertyChanged
{
private string sourceProperty;
public string SourceProperty
{
get { return sourceProperty; }
set
{
if (value != sourceProperty)
{
sourceProperty = value;
NotifyPropertyChanged("SourceProperty");
}
}
}
// boilerplate stuff
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public class MyForm : Form
{
private MyControl myControl;
public MyForm()
{
// create the datasource
var dataSource = new MyDataSource() { SourceProperty = "test" };
// bind a property of the datasource to a property of the usercontrol
myControl.DataBindings.Add("ControlProperty", dataSource, "SourceProperty",
false, DataSourceUpdateMode.OnPropertyChanged); // note the update mode
}
}
(I have tried this using a BindingSource, but the result was the same.)
Now what I want to happen is that when the value of MyControl.ControlProperty changes, the change is immediately propagated to the datasource (the MyDataSource instance). To achieve this I call OnValidating() in the usercontrol after changing the property. If I don't do that, I have to wait until validation gets triggered by a focus change, which is the equivalent of the "OnValidation" update mode, rather than the desired "OnPropertyUpdate" validation mode. I just don't feel like calling OnValidating() after altering a property value is the right thing to do, even if it (kind of) works.
Am I right in assuming the calling OnValidating() is not the right way to do this? If so, how do I notify the datasource of the ControlProperty change?
I think I've got this figured out. I didn't understand how change notifications were sent from control to bound datasource.
Yes, calling OnValidating() is the wrong way.
From what I've pieced together, there are two ways a control can notify the datasource that a property has changed.
One way is for the control to implement INotifyPropertyChanged. I had never done this from the control side before, and I thought only the datasource side of the binding had to implement it.
When I implemented INotifyPropertyChanged on my user control, and raised the PropertyChanged event at the appropriate time, it worked.
The second way is for the control to raise a specific change event for each property. The event must follow the naming convention: <propertyname>Changed
e.g. for my example it would be
public event EventHandler ControlPropertyChanged
If my property was called Foo, it would be FooChanged.
I failed to notice the relavent part of the MSDN documentation, where it says:
For change notification to occur in a
binding between a bound client and a
data source, your bound type should
either:
Implement the INotifyPropertyChanged
interface (preferred).
Provide a change event for each
property of the bound type.
This second way is how all existing WinForms controls work, so this is how I'm doing it now. I use INotifyPropertyChanged on my datasource, but I raise the Changed events on my control. This seems to be the conventional way.
Implementing the INotifyPropertyChanged interface is very simple. Here is a sample that shows an object with a single public field...
public class Demo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
private string _demoField;
public string DemoField
{
get {return demoField; }
set
{
if (value != demoField)
{
demoField = value;
NotifyPropertyChanged("DemoField");
}
}
}
}
Then you would create a Binding instance to bind a control property to a property (DemoField) on your source instance (instance of Demo).