c#


Binding different Models/pPoperties in the same ItemsControl


I have an ItemsControl whose ItemsSource is currently bound to an ObservableCollection of strings. For each item in the ItemsSource, two comboboxes and one textblock will appear.
Now, I have two different models, only one instance of each. The first combobox lists the names of these models. When chosen, I want the second combobox to populate with an ObservableCollection of strings representing the different fields in these models. Finally, the textblock will show the value of the chosen field from the second combobox.
Basically my problem is, I'm not creating new instances of these models every time I add an item to the first collection. That's just a dummy collection to make the controls appear. As I said above, I only have one instance of each of the six models that I want to bind to. The same model/property could be displayed multiple times over different combobox/textblock sets.
My ModelBase class, DataModel + two sample models are below. Each has an observablecollection containing strings representing the properties in the models (not showing all of them, but they are all strings):
public abstract class ModelBase : INotifyPropertyChanged
{
private ObservableCollection<string> _fieldList = new ObservableCollection<string>();
{
get { return _fieldList; }
}
private ObservablePairCollection<string, string> _fields = new ObservablePairCollection<string, string>();
public override ObservablePairCollection<string, string> Fields
{
get { return _fields; }
}
private string _name;
public string Name {
get { return _name; }
protected set {
if (_name != value) {
_name = value;
OnPropertyChanged("Name");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class DataModel : INotifyPropertyChanged
{
private ObservableCollection<ModelBase> models = new ObservableCollection<ModelBase>();
public ObservableCollection<ModelBase> Models
{
get { return models; }
set { models = value; OnPropertyChanged("Models"); }
}
private ModelBase _selectedModel;
public ModelBase SelectedModel
{
get { return _selectedModel; }
set { _selectedModel = value; OnPropertyChanged("SelectedModel"); }
}
private object _selectedField;
public object SelectedField
{
get { return _selectedField; }
set { _selectedField = value; OnPropertyChanged("SelectedField"); }
}
}
public class GPHDTModel: ModelBase
{
public GPHDTModel()
{
// It's a bad and dangerous habit to mess with private fields.
// Nothing but the public property's get/set blocks should touch the
// private field. One day you'll set _name and wonder why PropertyChanged
// wasn't raised. Make a habit of avoiding that risk.
Fields.Add("MessageID", "");
Name = "GPHDT";
}
public string MessageID
{
get { return Fields[0].Value; }
set { Fields[0].Value = value; OnPropertyChanged("MessageID"); }
}
}
public class PASHRModel: ModelBase
{
public PASHRModel()
{
Fields.Add("Heading", "");
Name = "PASHR";
}
public string Heading
{
get { return Fields[0].Value; }
set { Fields[0].Value = value; OnPropertyChanged("Heading"); }
}
}
Relevant parts of the viewmodel below. The DataModelCollection is just a collection of DataModels. The NmeaType collection is what the first combobox in each set of items should bind to. And then there's the six instances of my Models:
public class MainWindowViewModel : INotifyPropertyChanged
{
private ObservableCollection<DataModel> _dataModelCollection = new ObservableCollection<DataModel>();
public ObservableCollection<DataModel> DataModelCollection
{
get { return _dataModelCollection; }
set { _dataModelCollection = value; OnPropertyChanged("DataModelCollection"); }
}
private ObservableCollection<ModelBase> models = new ObservableCollection<ModelBase>();
public ObservableCollection<ModelBase> Models
{
get { return models; }
set { models = value; OnPropertyChanged("Models"); }
}
GPHDTModel gphdgModel = new GPHDTModel();
PASHRModel pashrModel = new PASHRModel();
public MainWindowViewModel()
{
//add each NMEA model to the dictionary
models.Add(gphdtModel);
models.Add(pashrModel);
}
public void AddDataModel(object parameter)
{
DataModelCollection.Add(new DataModel { Models = models });
}
}
Finally my view.
<ItemsControl ItemsSource="{Binding DataModelCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<ComboBox x:Name="NMEAlist"
DisplayMemberPath="Name"
ItemsSource="{Binding Models}"
SelectedItem="{Binding SelectedNmeaString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox x:Name="ModelList"
DisplayMemberPath="Key"
ItemsSource="{Binding SelectedNmeaString.Fields, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedField, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Value" />
<TextBlock Text="{Binding SelectedItem.Value,
ElementName=ModelList, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Well, this may not be the best answer, but it certainly should be able to accomplish what you want.
I would perhaps suggest using a converter. Assuming you already know what all these values are and all the collections you would like to return. The example I will show, will give you a basic concept, however you will need to orchestrate it to your liking.
Anyways, first create a converter:
public class StringToNmeaConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string sValue = (string)value;
if (sValue == "PASHR")
{
{
return new ObservableCollection<string>()
{
"Foo",
"Bar",
"Foobar",
"Barfoo"
};
}
}
if (sValue == "GPGGA")
{
{
return new ObservableCollection<string>()
{
"Oof",
"Rab",
"Raboof",
"Oofrab"
};
}
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then we want to have this converter in our XAML as a resource.
<Window.Resources>
<local:StringToNmeaConverter x:Key="NmeaConverter"></local:StringToNmeaConverter>
</Window.Resources>
And then we want to convert the combobox's selected item to the collection we want, and bind that to its item source.
<StackPanel>
<ComboBox x:Name="mainCombo">
<ComboBox.Items>
<sys:String>PASHR</sys:String>
<sys:String>GPGGA</sys:String>
</ComboBox.Items>
</ComboBox>
<ComboBox x:Name="NmeaCombo"
ItemsSource="{Binding ElementName=mainCombo, Path=SelectedItem,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource NmeaConverter}}"/>
<TextBox Text="{Binding ElementName=NmeaCombo, Path=SelectedItem,
UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>

Related Links

Can a windows service be used on a Silverlight website?
List object properties that have an attribute applied
WPF C# - XML Edit Binding in Treeview
How to format a String to display on multiple Lines
Total upload speed is slower when all connections are accepted by one TcpListener
Clearly recognize a certificate in Windows certificate store
TransactionScope and SQL Transaction
How to overwrite an existing image with c#?
Access IIS Websites Properties Using ServerManager
ReadResponse() failed: When uploading large amounts of data
c# development, what type of files store resources (for localization)?
Sharing/storing video
Databind to List<> with Entity Framework
How to send a message and receive a response on the same socket
Aggregate Roots
Panel fixed position

Categories

HOME
alasql
locale
azure-eventhub
gap-system
arcgis
magento-1.9.2.1
sms
jshell
multipartform-data
richtextbox
clip-path
pip
apache-httpclient-4.x
dynamics-crm-2011
chef-recipe
camunda
pylint
android-actionbar
accordion
ajaxcontroltoolkit
inline-assembly
android-cursorloader
ballerinalang
gulp-jshint
hierarchical-data
marionette
bytebuffer
xlib
apm
overflow
textview
loopback
ng2-bootstrap
epub
rtos
android-scrollview
android-databinding
origami
rbac
wicket-tester
colorbox
peerjs
amazon-rds-aurora
hierarchical-clustering
extjs3
vertex
enet
px4
webmatrix
qt3d
easy-thumbnails
glade
alfred
ldd
rowname
geokit
csc
supervised-learning
nd4j
stdlist
ideavim
std
markerspiderfier
matlab-engine
computability
ios8-share-extension
imageicon
tvp
photogrammetry
mathics
chunks
react-os
nsnotificationcenter
time-frequency
disabled-control
triplestore
step
email-headers
db2-connect
logo-lang
complete
lastinsertid
svg-android
randomaccessfile
caroufredsel
nsnumber
pyxplot
hypertable
google-email-audit-api
reflexil
win-prolog
joomla1.7
jqzoom
httppostedfilebase
vectorwise
javah
google-local-search
pixel-bender
user-preferences
moores-law

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App