The binding on my ItemsControl ItemsTemplate does not work. I've gone through some other similar stack overflow questions but I cannot figure out the problem with my binding. Can someone please show me what I am doing wrong with my binding?
Excerpt from my MainWindow's ViewModel;
private ObservableCollection<uint> words;
private uint word;
private int numberOfWords;
public ObservableCollection<uint> Words
{
get
{
return this.words;
}
set
{
this.words = value;
this.NotifyPropertyChanged(m => m.Words);
}
}
public uint Word
{
get
{
return this.word;
}
set
{
this.word = value;
this.NotifyPropertyChanged(m => m.Word);
}
}
public int NumberOfWords
{
get
{
return this.numberOfWords;
}
set
{
this.numberOfWords = value;
this.NotifyPropertyChanged(m => m.NumberOfWords);
this.Words.Clear();
for (uint x = 0; x < value; x++)
{
this.Words.Add(this.Word);
}
}
}
I have the below ItemsControl inside a user control. The MainWindow has its DataContext set to a ViewModel, which the ItemsControl uses. The ItemsSource binding works and I get however many textboxes I specify, but when putting a value in the TextBox, the binding does not work.
<ItemsControl Grid.Row="0" Grid.Column="1" Grid.RowSpan="8" ItemsSource="{Binding Words}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Word}" Width="125" Height="25" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I saw one post that talks about using this type of binding below, but apparently, I do not understand FindAncestor, so I do not know if I am on the right track or not with this.
Text="{Binding Path=Word, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"
You cannot bind to elements in a collection and then change the element itself--you can only change properties of this element through the binding. In other words, given the following collection
[ "one", "two", "three" ]
through a binding such as
<TextBox Text="{Binding Words[0]} /> <!-- the word "one" is displayed in the tb -->
if you change "one" to "derp" you would not alter the collection to
[ "derp", "two", "three" ]
To apply this to your example, you would want to bind the collection to the ItemsControl, then in the template bind to each instance within the collection and change properties of this instance.
First, create your Model. This holds your data and is what you bind against in the UI.
public sealed class Word
{
public uint Value {get;set;}
}
Next, expose a collection of these on your View Model.
public sealed class ViewModel
{
//create and fill in ctor
public ObservableCollection<Word> WordsYo {get;private set;}
}
Next, bind your ItemsControl's ItemsSource to this property and bind elements in the template to the properties of Word:
<!-- Window.DataContext is set to an instance of ViewModel -->
<ItemsControl ItemsSource="{Binding WordsYo}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Value}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The Aristocrats.
Related
I'm new to wpf, I created a listbox it will create a dynamic listitems,Here I used datetemplate which contains two controls that is two textblocks, one textblocks contains binding a values form combobox(which is string datatype),The other one is, bind a value from code bind.
XAML
<ListBox ItemsSource="{Binding obj}" HorizontalContentAlignment="Left" x:Name="lstbxindex" SelectionMode="Extended" Foreground="White" FontSize="20px" Height="201" BorderBrush="#555555" Margin="80,40,0,0" VerticalAlignment="Top" Width="282" Background="#555555" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5" >
<TextBlock Height="40px" Width="80px" Text="{Binding roundedhourvalue, FontSize="24" Background="#555555" Foreground="White"></TextBlock>
<TextBlock x:Name="items" Text="{Binding}" Margin="35,0,0,0"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C# (Roundedhour.cs)
public class Roundedhour
{
public string hourvalue { get; set; }
public override string ToString()
{
return string.Format("{0}", hourvalue);
}
}
In this class create a property for hourvalue. For this class I created a object in codebehind file which I mentioned below.create a object and assign a value for hourvalue variable.
C# (Code Behind)
{
if (dispatcherTimer1.Interval == TimeSpan.FromSeconds(15))
{
//lstbxindex.Items.Add(lstbxindex.SelectedItem.ToString());
string hrvalue = Convert.ToString(hrvalueinitially);
obj = new Roundedhour();
obj.hourvalue = Convert.ToString(hrvalueinitially);
string roundedhourvalue =obj.hourvalue;
this.DataContext = this;
//lblprojectAhr.Content = string.Join(",", hrvalueinitially + "" + "hr");
}
}
Here, I created a object for Rounderhour class.Assign values to that property hour value. But I cannot be bind a value from codebind to XAML page.
Your ItemsSource should be of an CollectionType.
ListBox ItemsSource="{Binding obj}"
You should also start to give your variables and properties meaningful names. That makes it easier to read your code later on.
The second Problem is in your Binding itself.
You are binding like this: Text="{Binding roundedhourvalue}
So WPF is expecting a property roundedhourvalue on obj.
But as shown in your CodeBehind there is only obj.hourvalue.
So change your Binding to Text="{Binding hourvalue}
Check your Output-Window for details.
NOTE:
string roundedhourvalue = obj.hourvalue;
has no getter and is not accsessible since its private.
NOTE: You either use a Binding OR your set the ItemsSource in CodeBehind.
Try it like this:
Just remove all the formatting and stuff:
<ListBox ItemsSource="{Binding RoundedHours}" x:Name="ListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5" >
<TextBlock Text="{Binding hourvalue}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And change your code-behind to this:
private void UpdateDataContext(object hrvalueinitially)
{
List<Roundedhour> hours = new List<Roundedhour>();
hours.Add(new Roundedhour()
{
hourvalue = hrvalueinitially.ToString()
});
//Set the ItemsSource in code: => remove your ItemsSource Binding from XAML
listBox.ItemsSource = hours;
}
OR your can use an 'MVVM' approach:
public class MyViewModel : INotifyPropertyChanged
{
//IMPLEMENT INotifyPropertyChanged HERE PLS
public ObservableCollection<RoundedHour> Collection { get; set; } = new ObservableCollection<RoundedHour>();
private void AddToCollection(object hrvalueinitially)
{
Collection.Add(new RoundedHour()
{
hourvalue = hrvalueinitially.ToString()
});
OnPropertyChanged("Collection");
}
//Make sure to set your Windows DataContext to an Instance of this Class
}
Assign XAML object's "ItemsSource" property with your binding variable.
Also it's totally wrong binding object's itself into object's property like
this.DataTemplate = this;
Use:
List<yourobject> bindingObjectList = new List<yourobject>();
// insert your objects into the list
this.ItemsSource = bindingObjectList;
Here you can find an example:
Grid & Pivot Binding Example for multiple DataTemplates
I have a custom object that consists of 2 properties. The first is a string that i wish to use as a summary or header in the tree view. The second is a list of a custom type that contains objects that are to be included under each header. The objects contain things such as name, id, area, etc.. Ill most likely default to the name property of those list objects. How can I push this into a tree view.
Concatenated Model
public class WVWellModel : Notifier
{
private string _API;
public string API
{
get
{
return this._API;
}
set
{
this._API = value; OnPropertyChanged("API");
}
}
private string _WellName;
public string WellName
{
get
{
return this._WellName;
}
set
{
this._WellName = value; OnPropertyChanged("WellName");
}
}
private string _Division;
public string Division
{
get
{
return this._Division;
}
set
{
this._Division = value; OnPropertyChanged("Dvision");
}
}
private string _Area;
public string Area
{
get
{
return this._Area;
}
set
{
this._Area = value; OnPropertyChanged("Area");
}
}
private string _FieldOffice;
public string FieldOffice
{
get
{
return this._FieldOffice;
}
set
{
this._FieldOffice = value; OnPropertyChanged("FieldOffice");
}
}...............
** Model that will be put in a list to be injected into tree view**
public class groupingModel : Notifier
{
private string _Header;
public string Header
{
get { return _Header; }
set { _Header = value; OnPropertyChanged("Header"); }
}
private List<WVWellModel> _Wells;
public List<WVWellModel> Wells
{
get { return _Wells; }
set { _Wells = value; OnPropertyChanged("Wells"); }
}
}
List of Custom Type to be injected into tree view
List treeViewList = someMethod();
In summary, I would like to bind my tree view to a custom list object.List<groupingModel> The object in those lists have two properties, a string header that is to be used to group the objects in the tree view, and a second property that contains a list of custom objects "WVWellModel".
EDIT TO XAML to Allow Selection of all items in group
I've attempted to go ahead and make the group selectable with he goal that if the group is selected all children are selected underneath. Ive successfully bound it to a property inside of the group called "IsChecked". it defaults to false and works successfully. The problem is i am unable to capture the change in value and thus cannot run any logic to select its children.
<TreeView DockPanel.Dock="Bottom" ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="wellModel:WellGroupModel" ItemsSource="{Binding Wells}">
**<CheckBox Content="{Binding Header}" IsChecked="{Binding IsChecked}"/>**
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type wellModel:WellModel}">
<CheckBox Content="{Binding WellName}" IsChecked="{Binding IsSelected}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The TreeView control uses HierarchicalDataTemplate to control how items are displayed and how their children are populated. If your item class has children of a different type, it can specify its own child ItemTemplate, and so on recursively.
I've also added a minimal top-level viewmodel which owns a collection of GroupingModel. I'm using conventional C# naming conventions: Classes and properties start with a capital letter, private fields start with an underscore and a lower-case letter. It seems silly but when everybody uses the same convention, you always know what you're looking at.
Finally, I used ObservableCollection<T> rather than List<T>. If you bind an ObservableCollection to a control, then you can add/remove items in the collection and the control will automatically be notified and update itself without any additional work on your part.
XAML
<TreeView
ItemsSource="{Binding Groups}"
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:GroupingModel}"
ItemsSource="{Binding Wells}"
>
<TextBlock Text="{Binding Header}" />
<HierarchicalDataTemplate.ItemTemplate>
<!-- This can be DataTemplate if no child collection is specified -->
<DataTemplate
DataType="{x:Type local:WVWellModel}"
>
<TextBlock Text="{Binding WellName}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Alternatively, if you have heterogeneous collections of objects, you can create implicit templates as resources and let them be applied by type rather than by hierarchy. In your particular case, this will produce identical results, because you have a strict item hierarchy.
<TreeView
ItemsSource="{Binding Groups}"
>
<TreeView.Resources>
<HierarchicalDataTemplate
DataType="{x:Type local:GroupingModel}"
ItemsSource="{Binding Wells}"
>
<TextBlock Text="{Binding Header}" />
</HierarchicalDataTemplate>
<DataTemplate
DataType="{x:Type local:WVWellModel}"
>
<TextBlock Text="{Binding WellName}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
C#
public class ViewModel : Notifier
{
public ViewModel()
{
Groups = new ObservableCollection<GroupingModel>
{
new GroupingModel {
Header = "First Group",
Wells = new List<WVWellModel> {
new WVWellModel() { WellName = "First Well" },
new WVWellModel() { WellName = "Second Well" },
new WVWellModel() { WellName = "Third Well" },
}
},
new GroupingModel {
Header = "Second Group",
Wells = new List<WVWellModel> {
new WVWellModel() { WellName = "Third Well" },
new WVWellModel() { WellName = "Fourth Well" },
new WVWellModel() { WellName = "Fifth Well" },
}
}
};
}
#region Groups Property
private ObservableCollection<GroupingModel> _groups = new ObservableCollection<GroupingModel>();
public ObservableCollection<GroupingModel> Groups
{
get { return _groups; }
set
{
if (value != _groups)
{
_groups = value;
OnPropertyChanged(nameof(Groups));
}
}
}
#endregion Groups Property
}
Update
Let's make the WVWellModel items checkable. First, we'll give them a boolean property that we'll bind to the checkbox's IsChecked property:
public class WVWellModel : Notifier
{
private bool _isSelected;
public bool IsSelected
{
get
{
return this._isSelected;
}
set
{
this._isSelected = value; OnPropertyChanged();
}
}
And then we'll change the content in the WVWellModel DataTemplate from a TextBlock to a CheckBox:
<DataTemplate
DataType="{x:Type local:WVWellModel}"
>
<CheckBox
Content="{Binding WellName}"
IsChecked="{Binding IsSelected}"
/>
</DataTemplate>
You can put any valid XAML UI in a template as long as there's a single root element.
<TreeView
Width="300"
Height="200"
ItemsSource="{Binding Groups}"
Grid.IsSharedSizeScope="True"
>
<TreeView.Resources>
<HierarchicalDataTemplate
DataType="{x:Type local:GroupingModel}"
ItemsSource="{Binding Wells}"
>
<TextBlock Text="{Binding Header}" />
</HierarchicalDataTemplate>
<DataTemplate
DataType="{x:Type local:WVWellModel}"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="CheckBoxColumn" />
<ColumnDefinition Width="Auto" SharedSizeGroup="APIColumn" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
Content="{Binding WellName}"
IsChecked="{Binding IsSelected}"
/>
<TextBlock
Grid.Column="1"
Margin="12,0,0,0"
Text="{Binding API}"
HorizontalAlignment="Right"
/>
</Grid>
</DataTemplate>
</TreeView.Resources>
</TreeView>
I´m trying to bind a ListBox to a ObservableCollection. I wan´t to bind the Text Properties of the ListBox entrys and the Background of the ListBox entrys.
The ListBox is defined in an loaded loose xaml file:
<TextBox Margin="0,5,5,5" Text="{Binding Path=TB9P}" Background="LightBlue" Name="DetailsviewTB9" Height="20">
<TextBox.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="Blue" Foreground="White">Daten</Label>
<ListBox ItemsSource="{Binding Source={StaticResource res_LB1P}}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StringP}" Background="{Binding Path=SelectedItemP, Converter={StaticResource c_SelectedItemToBackgroundConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</TextBox.ToolTip>
</TextBox>
The DataContext is set on class DetailsViewText
public class LBEntry
{
bool DetailsViewLBSelectedItem = true;
string DetailsViewLB = "test";
public LBEntry(bool selcected, string str)
{
DetailsViewLB = str;
DetailsViewLBSelectedItem = selcected;
}
public bool SelectedItemP
{
get { return DetailsViewLBSelectedItem; }
set { DetailsViewLBSelectedItem = value; }
}
public string StringP
{
get { return DetailsViewLB; }
set { DetailsViewLB = value; }
}
}
public class LBEntrysCollection : System.Collections.ObjectModel.ObservableCollection<LBEntry>
{
//
}
public class DetailsViewText
{
string[] DetailsViewTB1_Text = new string[20];
bool[] fDetailsViewCB = new bool[20];
LBEntrysCollection[] LBEntrys = new LBEntrysCollection[]{
new LBEntrysCollection{ new LBEntry(false, "test"), new LBEntry(true, "test") },
new LBEntrysCollection{ new LBEntry(true, "test") },
new LBEntrysCollection{ new LBEntry(false, "test") },
new LBEntrysCollection{ new LBEntry(false, "test") },
new LBEntrysCollection{ new LBEntry(false, "test") }
};
public LBEntrysCollection LB1P
{
get { return LBEntrys[0]; }
set { LBEntrys[0] = value; }
}
public string TB9P
{
get { return DetailsViewTB1_Text[8]; }
set { DetailsViewTB1_Text[8] = value; }
}
...
}
The resource res_LB1P is set in the mainWindow constructor:
// Resources
this.Resources.Add("res_LB1P", detailsViewFrameHandling.DetailsViewTextP.LB1P);
Basicly I just want to bind the ListBox to a LBEntrysCollection with SelectedItemP as switch for the background Color and StringP as the Text Property. But I need the DataContext on DetailsViewText for other Propertys.
I´m getting an Exception when the xaml File is loading the StaticResource res_LB1P.
How do I have to set my Binding on ListBox and TextBlock to get it right?
EDIT:
With this
<ListBox ItemsSource="{Binding Path=LB1P}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=LB1P.StringP}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Items are added, but there is no Text shown in the TextBox
Now I´m really confused. It does work like this:
<ListBox ItemsSource="{Binding Path=LB1P}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StringP}" Background="{Binding Path=SelectedItemBrushP}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Simple enough, but I thought i had tried this before and it didn´t work...
Is it possible, that if one Binding does fail (the Background Binding) the other Binding (Text Property) does also not work?
I have always considered the ViewModel (the object the DataContext points to) to be just that: a Model of the View.
So to solve this, you need either one object that will be the ViewModel because there is only one DataContext property or you will need to add an extra DataContext-like property.
The first option (one ViewModel) can be realized by creating a new class that contains both the ObservableCollection and the DetailsViewText:
class ComposedViewModel: INotifyPropertyChanged
{
public LBEntrysCollection LBEntries
{
get { ... }
set { ... }
}
public DetailsViewText Details
{
get { ... }
set { ... }
}
}
The second option (extra DataContext-like property) can be realized by sub-classing the ListBox and adding another property.
Why not do this ?
<ListBox ItemsSource="{Binding ElementName=<TextBox's Name>, Path=DataContext">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StringP}" Background="{Binding Path=SelectedItemP, Converter={StaticResource c_SelectedItemToBackgroundConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Correct me if I'm wrong with understanding your question. You want to bind the listbox's itemssource to the textbox's datacontext?
I'm completely new to WPF.
I'm making a simple application in the MVVM pattern.
I have a viewmodel with a model referenced in it. The model contains some netelements I want to put in a combobox.
Here is the relevant part of the viewmodel:
public class MainWindowVM : ViewModelBase
{
private Model _model = null;
public Model Model
{
get
{
return _model;
}
}
#region ActiveElement
private NetElement _activeElement = null;
public NetElement ActiveElement
{
get
{
return _activeElement;
}
set
{
if (_activeElement != value)
{
_activeElement = value;
RaisePropertyChanged("ActiveElement");
if (ActiveElementChanged != null)
ActiveElementChanged(this, EventArgs.Empty);
}
}
}
}
I would like to be able to select a NetElement in a combobox and set the ActiveElement to it.
here is the relevant part of my current XAML:
<ItemsControl Background="White" IsTabStop="True" ItemsSource="{Binding Path=Model.RootNet.Elements}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Margin="2,6">
<Hyperlink Command="{Binding Path=I'm not able to figure out what to write here}">
<TextBlock Text="{Binding Path=Name}" />
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is not a combobox but a list of TextBlocks, but you can see where it is going.
How can I set the ActiveElement from the view?
Create a binding for the SelectedItem property of the ComboBox to your ActiveElement property:
<ComboBox SelectedItem="{Binding Path=ActiveElement}" ... />
then set the DataContext property of the view to your view model.
I'm databinding a listbox to an object that contains two array of strings. Each listbox item is set to a data template made up of a textbox and a combo box. The first string array is bound to the list, and the second string array is bound to the combo box. Well, at least that's I'm trying to achieve. The problem is that I can't figure out the binding syntax to set the second array to the combo box. Here's what I have:
The first thing is my class with my two string arrays. Pretty straightforward. Please note that the string array content is there for simplicity.
public class JobAssignments
{
public JobAssignments()
{
m_people.Add("John");
m_people.Add("Bill");
m_people.Add("Frank");
m_people.Add("Steve");
m_jobs.Add("Architect");
m_jobs.Add("Teacher");
m_jobs.Add("Carpenter");
m_jobs.Add("Plumber");
}
private List<string> m_people = new List<string>();
public List<string> People { get { return m_people; } set { m_people = value; } }
private List<string> m_jobs = new List<string>();
public List<string> Jobs { get { return m_jobs; } set { m_jobs = value; } }
};
In code, I set an instance of this class as the datacontext of this listbox:
<ListBox x:Name="listBox"
Grid.Row="0"
HorizontalContentAlignment="Stretch"
DataContext="{Binding}"
ItemsSource="{Binding People}"
ItemTemplate="{StaticResource JobAssignmentDataTemplate}">
</ListBox>
With a data template that looks like this:
<DataTemplate x:Key="JobAssignmentDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding}"/>
<ComboBox Grid.Column="2"
SelectedIndex="0"
ItemsSource="{Binding Jobs ???? }"/>
</Grid>
</DataTemplate>
What I usually get out my experiments is a list box of People, but the combo box of each list item is empty.
I can get it to work if I use
ItemsSource="{Binding ElementName=listBox, Path=DataContext.Jobs }"/>
but I don't want to use ElementName as it hardcodes the source of the array a specific listbox which I'd like to avoid.
Trying something like
ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=Parent.Jobs}"/>
Doesn't seem to work either as it's looking for Jobs inside the Grid.
A little push in the right direction would help greatly.
Thanks!
I had roughly the same problem as you except I had a listbox within a tabcontrol. I was able to solve it by using getting the tab control that contained the listbox. Sample code as follows:
<TabControl ItemsSource="{Binding Groups, Mode=TwoWay}" SelectedItem="{Binding SelectedGroup, Mode=TwoWay}">
<TabControl.ContentTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabControl, AncestorLevel=1}, Path=DataContext.ItemsInGroup, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ItemGroup}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
When you are at DataTemplate that represents just one People your JobAssignments instance is not there. Try the below
ItemsSource="{Binding ElementName= listBox, Path=Jobs}"/>
But I dont recommend the above step. You need to refactor your ViewModel logic. I guess 'Jobs' can be a static instance so that you can do a x:Static binding
ItemsSource="{Binding Source={x:Static JobAssignments}, Path=Jobs}"
You probably need to modify your object structure to work like this:
public class Person
{
public string Name;
public IEnumerable<string> Jobs;
}
public class JobAssignments
{
public JobAssignments()
{
Jobs.Add("Architect");
...
People.Add(new Person() { Name = "Bob", Jobs = Jobs });
...
}
private List<Person> m_people = new List<Person>();
public List<Person> People { get { return m_people; } }
private List<string> m_jobs = new List<string>();
public List<string> Jobs { get { return m_jobs; } }
}
Then, you can remove the question marks, and things should work.