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

Unbound DataGridView causing causing index was out of range error
how to publish c# database project
WPF style DatePicket Prev & Next buttons
Azure Service Bus DeadLetter QUEUE
Windows application and database connection
Large data table to multiple csv files of specific size in .net
Entity Framework SqlQuery Select LONG RAW into byte array
Disposable wrapper class for PInvoke structure with handles
Facing issues with POST Actions on live server
How to simplify conventional routing templates?
Unity3D Move Camera with mouse on HORIZONTAL axis [duplicate]
2 Different DropDownList in the same position selected by radiobutton
Serializing a “complex” class c#
C#, How Do I Get Mono Configured on Windows Powershell (Windows 10)? (Environmental Variable PATH)
UTF-8 Byte Mark check gives different value based on operating system
C# - Packet being sent but client not receiving it

Categories

HOME
reactjs
max
sql-server-2014
compression
snappy
c++builder
dynamic
crash
powerquery
yuv
virtualhost
ionic-native
cracking
jcodemodel
guidewire
solidity
derby
brightway
sonarlint
single-page-application
combinations
beaker-notebook
opengraph
onclicklistener
chartist.js
windows-mobile
traveling-salesman
marionette
angular-schema-form
federated
kubectl
unity3d-5
availability
dropdownbox
leaderboard
mongoid5
iterm2
armadillo
cowboy
idea-plugin
socketcluster
pyexcel
autodesk-data-management
bzip2
qt-quick
grails-2.0
android-doze-and-standby
automapper-4
pyopenssl
appcmd
px4
playframework-2.3
node-java
sharpssh
seyren
boost-regex
dynatable
blitz3d
portaudio
toggleclass
disconnect
qtruby
queuing
camellia
paypal-subscriptions
nugetgallery
custom-build-step
calc
fadein
nonblocking
app-data
android-facebook
tvp
lytro
radgrid
indices
xcode5
mind-manager
smartxls
email-headers
acrofields
nomachine
node-amqp
facebook-likebox
ie-developer-tools
pageload
architectural-patterns
reference-manual
configurationsection
gssapi
motordriver
openafs
doxia
erlide
jqzoom
rjs
netbeans7.0
onunload
database-agnostic
mysql-logic
code-golf
appointment
morfik
focus-stealing
rpxnow
file-icons
managed-code

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