I'm maintaining some old WinForms in NET Framework 3.5 in both Visual Basic and C#, but I'm having a hard time trying to binding to a POCOs data class.
I got this (using INotifyPropertyChanged):
public string DisplayUnits
{
get { return _displayUnits; }
set
{
_displayUnits = value;
NotifyChange("DisplayUnits");
}
}
public string SetUnit
{
get { return _setUnit; }
set
{
_setUnit = value;
NotifyChange("SetUnit");
}
}
Setting the SetUnit is not a problem since I got this:
ComboxBoxUnits.DataBindings.Add("SelectedItem", data, "SetUnit", False, DataSourceUpdateMode.OnPropertyChanged)
and that works since it's a string to a string, but the data.DisplayUnits is a string ie. "inch;feet;yard;mm;cm;m" and currently the way the ComboBox is populated is like this:
ComboBoxUnits.Items.AddRange(data.DisplayUnits.Split(";"));
Also, there is a way for the user to add and remove items from that list. So when I need to do Items.Add or Items.Remove, how can I bind it to DisplayUnits property and fire a change whenever the combobox item list is updated?
Conversely, it has to be two-way databinding like in WPF. When the data.DisplayUnits is updated by another process (ie: ft2;yard2;cm2;m2) from when they change to different "Products" (like the first product will measure length and the second product will measure approximate areas), I need to update the UI to reflect those changes in the Combox.Items
In MVVM, I could try and use a ITypeConverter (Convert, ConvertBack) but I don't think it's supported in WinForms; but there has to be a way to format the Combobox.Items to the POCOs property of the data class, and for the POCO class to be converted back the same for the Winform.
Any ideas?
UPDATE: To clarify -- The reason why I am keeping it in Plain Old CLR Object (POCO) is because the "data" will be used for XML Serialization. The XML file is going to be downloaded to custom machine using a PIC processor. The ";" is used for parsing. Therefore, the DisplayUnit must be in this format "in;ft;yd".
Also, this is going to be compiled in VS2008 since a touchscreen we use is running WinCE 6.5. Half will be in C# while the other half is going to be in Visual Basic.
I don't know if I understand you right here but from what I can make out, you need to set the DataSource property of your ComboBox. This is how I would do it in Winforms:
Add a class that defines the DataSource of your ComboBox:
class ComboDataSource
{
// Display is the property shown as item in your ComboBox (DisplayMember)
public string Display { get; set; }
// you could also add a ValueMember ID or something
}
Add a method that takes your DisplayUnits as a parameter and cuts your string into a string array. Go through the strings and create and add your ComboDataSource. Assign the list to the ComboxBoxUnits.DataSource. Define the DisplayMember (of course it is the Display property of the ComboDataSource)
private void UpdateDataSource(string data)
{
var split = data.Split(';');
List<ComboDataSource> list = new List<ComboDataSource>();
foreach (var item in split)
list.Add(new ComboDataSource() { Display = item });
ComboxBoxUnits.DataSource = list;
ComboxBoxUnits.DisplayMember = "Display";
}
For this example I created a class that wraps your DisplayUnits and SetUnit(s) properties. (I didn't implement SetUnit) Implement the INotifyPropertyChanged interface.
class Data : INotifyPropertyChanged
{
private string _displayUnits;
public string DisplayUnits
{
get { return _displayUnits; }
set
{
_displayUnits = value;
OnPropertyChanged("DisplayUnits");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Then you can create your Data object in your code. Something like this...
Data data = new Data();
Subscribe to the PropertyChangedEvent...
data.PropertyChanged +=(sender, args) => UpdateDataSource(data.DisplayUnits); // pass in the DisplayUnits
Set the data...
data.DisplayUnits = "cm;km;feet;yard";
PropertyChanged event will fire and update your DataSource and so the items displayed in your ComboBox.
Hope this helps...
UPDATE: Remove item from ComboBox and rebind it. (buttonClick or something)
ComboDataSource selectedItem = comboBox1.SelectedItem as ComboDataSource;
if(selectedItem == null)
throw new NullReferenceException("selectedItem");
// get the DataSource back from the ComboBox
List<ComboDataSource> dataSource = comboBox1.DataSource as List<ComboDataSource>;
if (dataSource != null)
{
// remove it from the datasource
dataSource.Remove(selectedItem);
// so this is pretty 'straight forward' and certainly not best practice, but we put the datasource back up again the same way we have set it
string[] comboBoxItems = dataSource.Select(item => item.Display).ToArray();
// join the string (f.e. 'km;cm;feet') and update it again
string newDataSource = string.Join(";", comboBoxItems);
UpdateDataSource(newDataSource);
}