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

Update to Azure Notification hub tags fails when tags list is empty
Attempted to read or write protected memory on DAQ
AvalonEdit : Tab Key Handling
Binding error in design and runtime on usercontrol
Handle embedded browser 404 error from external DLL in WPF
How to send keys started hidden CMD process
How do I sort the strings I have in a textfile properly?
An exception of type 'System.Data.SqlClient.SqlException' occurred
c# wpf no choose image FileDialog in image
How do you set the language version for C# projects when generating projects with CMake?
Dynamic binding in winform combobox
How to access the HttpContext.Application other than Controller class ie.Outside of the Controlle
How can I serialize this xml array to a property in my class?
Truncate significant figures [duplicate]
How use IChangeToken to expire a token?
How to create shortcut of my project .exe in the same folder were .exe is located?

Categories

HOME
logging
google-cloud-pubsub
opencv4android
thermal-printer
comments
travis-ci-cli
python-3.4
clip-path
mamp
http-status-codes
camunda
webseal
box2d
web-parts
ibatis
windows-phone
novacode-docx
summernote
android-wifi
monad-transformers
wai-aria
ecmascript-2017
ithit-webdav-server
suitescript
pixels
datanucleus
continuous-fourier
windows-mobile
symlink
deferred
key-bindings
eclipse-jdt
webmock
odp.net
kofax
azure-storage-files
var
usernotifications
mixed-models
php-mongodb
cakephp-3.2
activeandroid
jscoverage
gige-sdk
aws-rds
fileopendialog
android-music-player
zsh-completion
glade
jspx
mate-desktop
scriptengine
django-celery
wonderware
joomla3.3
eggplant
gcc-warning
bungeecord
illegalargumentexception
nsnotificationcenter
agent-based-modeling
im4java
disabled-control
nspopupbutton
twitter-finagle
rda
sendy
smartxls
webshim
node-mongodb-native
starling-framework
nvcc
codio
netbeans-plugins
xcode6.1-gm-seed
thucydides
aspnet-compiler
forward-declaration
gwt2
microsoft-speech-platform
antixsslibrary
gssapi
states
dancer
mysql-connector
inserthtml
code-organization
jquery-click-event
sessiontracking
xhtmlrenderer
quazip
http-response-codes
conditional-operator
table-valued-parameters
browser-state
mdd

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