New problem
I spent all morning trying to figure out the C# / WPF equivalent of the following code in VB6:
lstFleet.AddItem rsFleet!FleetName
lstFleet.ItemData(lstFleet.NewIndex) = rsFleet!FleetID
In the above, rsFleet is a DAO recordset object that contains the result of a query and lstFleet is a listbox. ItemData is a property associated with each listbox entry that allows you to look up based on key rather than value. After two hours of searching online I realised there was no equivalent and figured out that databinding a WPF listbox to a C# collection was the modern way to handle this.
So now I have an object called FleetsList which contains the Fleet data from the database as well as various methods to manipulate that information. Within the FleetsList object is a Dictionary collection called Fleets that holds the actual data. So my code is as follows:
FleetsList.LoadFleets();
lstFleet.ItemsSource = FleetsList.Fleets;
lstFleet.DisplayMemberPath = "FleetName";
lstFleet.SelectedValuePath = "FleetID";
MessageBox.Show(lstFleet.Items.Count.ToString());
The Fleet information is loaded without any problems and the Fleets Dictionary object is populated. I set the ItemsSource for the lstFleets Listbox to the Dictionary object and also set the DisplayMemberPath to indicate what should appear in the listbox and the SelectedValuePath to FleetID. Unfortunately, the listbox is blank. However, it does contain the items because the messagebox at the end is showing the correct number of fleets. Also when I add a breakpoint to the following code, I can use debug to look at a selected item by clicking on the listbox and all the data for the entire Fleet record is there. The line fails though due to lstFleet.SelectedValue being null.
private void lstFleet_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show(lstFleet.SelectedValue.ToString());
}
So my question is, what I am doing wrong? The compiler is happy to accept the syntax but for some reason the DisplayMemberPath and SelectedValuePath are not being set? Also, is there anyway to filter what is displayed in the Listbox so that certain fleets can be excluded, on the basis of RaceID for example.
The relevant line of XAML for the above listbox is:
<ListBox DataContext="{Binding}" Height="187" ItemsSource="{Binding}" Margin="754,196,27,116" Name="lstFleet" Width="120" SelectionChanged="lstFleet_SelectionChanged" />
Help!!
EDIT: I have managed to display something by overriding the ToString function of Fleet. However, instead of returning just the FleetName it returns in the format of: [8842, Cargo Task Group], where 8842 is the FleetID. No idea why.
public override string ToString()
{
return this.FleetName;
}
EDIT2: If I remove the override function and also remove the calls to DisplayMemberPath and SelectedValuePath I get the listbox populated with the [8842, Cargo Task Group] format. The overidden function was being called as I put a breakpoint on it but it would seem it is being ignored in favour of the base class implementation for some reason. Now even more confused.
EDIT3: If I put the override back in but replace the FleetName return with "Hello World", the listbox is populated with [8842, Hello World]. I guess the default ouput of a listbox linked to a Dictionary collection must be a KeyValue pair and I am only overriding the Value part. Perhaps there is another function I can overwrite to prevent that but I am reluctant to do so in case I screw up the returning of KeyValue pairs when I really need them. Experimentation contines...
EDIT4: lstFleet.SelectedValuePath = "Key"; instead of lstFleet.SelectedValuePath = "FleetID" successfully returns the FleetID when I select one of the listbox items. Using lstFleet.DisplayMemberPath = "Value" instead of lstFleet.DisplayMemberPath = "FleetName" results in a listbox filled with "Diaspora.Fleet" where Diaspora is the name of the project.
EDIT5: I have tried a data template in XAML instead. Still getting the output of a list of "Diaspora.Fleet". I assume the syntax of Binding Path=Value is the problem. What do I need to use in its place? Really frustrating morning.
<ListBox DataContext="{Binding}" Height="187" ItemsSource="{Binding}" Margin="637,196,27,116" Name="lstFleet" SelectionChanged="lstFleet_SelectionChanged" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Steve