Setting String Values Across Pages in WP7 App - c#

I'll try my best to explain this without speaking too much about the specific content and purpose of the app. I'll just say on the main page there are 3 empty "slots" for items you can select to occupy them. When you click on one, it takes you to a separate page that let's you select a specific item for that slot. Here is the code to better explain:
<TextBlock Text="{Binding FirstSelectionName}" />
<TextBlock Text="{Binding FirstSelectionType}" />
<HyperlinkButton Content="Choose First Option"
Name="firstHyperLink"
NavigateUri="/Pages/FirstChoices.xaml"
/>
<TextBlock Text="{Binding SecondSelectionName}" />
<TextBlock Text="{Binding SecondSelectionType}" />
<HyperlinkButton Content="Choose Second Option"
Name="secondHyperLink"
NavigateUri="/Pages/SecondChoices.xaml"
/>
<TextBlock Text="{Binding ThirdSelectionName}" />
<TextBlock Text="{Binding ThirdSelectionType}" />
<HyperlinkButton Content="Choose Third Option"
Name="thirdHyperLink"
NavigateUri="/Pages/ThirdChoices.xaml"
/>
Here is the code behind for this XAML page:
public class FirstSelection
{
public string FirstSelectionName { get; set; }
public string FirstSelectionType { get; set; }
}
public class SecondSelection
{
public string SecondSelectionName { get; set; }
public string SecondSelectionType { get; set; }
}
public class ThirdSelection
{
public string ThirdSelectionName { get; set; }
public string ThirdSelectionType { get; set; }
}
On the selection pages an XML file is looped through and saved into new instances of a class. When the user selects a certain option from that list with a button press, I want to set the corresponding slot on the main page equal to that selection. Here is an example of the first slots selection page:
<ListBox Name="firstOptionsList">
<ListBox.ItemTemplate>
<DataTemplate>
<Button BorderThickness="3"
Click="setSelectedToFirst">
<StackPanel Orientation="Vertical">
<TextBlock Name="nameTextBlock"
Text="{Binding Name}"
/>
<TextBlock Name="typeTextBlock"
Text="{Binding Type}"
/>
</StackPanel>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And finally the code behind for the selectin page:
public FirstOptionsPage()
{
InitializeComponent();
Dispatcher.BeginInvoke((Action)(() => firstList.ItemsSource = firstdata));
WebClient firstWebClient = new WebClient();
firstWebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(first_DownloadStringCompleted);
firstWebClient.DownloadStringAsync(new Uri("http://www.website.com/firstoptions.xml"));
}
void first_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
XElement xmlitem = XElement.Parse(e.Result);
var firstdata = new List<FirstOptionsClass>();
foreach (XElement item in xmlitem.Elements("entry"))
{
var name = item.Element("name");
var namevalue = (name == null) ? null : name.Value;
var type = item.Element("type");
var typevalue = (type == null) ? null : type.Value;
firstdata.Add
(new FirstOptionsClass
{
Name = namevalue,
Type = typevalue,
}
);
}
firstList.ItemsSource = firstdata;
}
public class FirstOptionsClass
{
public string Name { get; set; }
public string Type { get; set; }
}
public System.Collections.IEnumerable firstdata { get; set; }
private void setSelectedToFirst(object sender, RoutedEventArgs e)
{
//THIS IS THE PART WHERE I'M NOT SURE HOW TO SET FirstOptionsClass Name = FirstSelectionName on the MainPage.xaml
}
See the comment line in the click event for my main problem. How to I set these values equal to eachother across these pages? I know it may look like a mess here so I appreciate the help.

TBH I'm not sure what you want to do. What fires setSelectedToFirst?
Anyways, to save some data and read it during app's lifycycle you can use IsolatedStorageSettings.

Related

Xamarin.Forms How to two-way bind to a control in Listview

Im having a hard time trying to figure out how to set up a two-way binding for a control inside a listview.
Im using ReactiveUI and Xamarin.Forms.
In this case i would like to load a list of objects that have a quantity. This is set initially when the page loads. However i would like to be able to change these quantity values in the view when the program is run. I used an Entry for that.
Setting up a two-way Binding for the List itself (done in code behind, the reactive way) is not possible. It will error.
Is there another way to observe changes done to the Text property in the Entry control and reflect them to the according item from the list in my viewmodel?
I've been having trouble finding a solution for this and don't really know how to go about this.
Here is my XAML code:
<CustomControls:AutoLoadListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="20,0,0,0" Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Margin="0,5,0,-5" Style="{StaticResource ViewCellPrimaryLabelStyle}" x:Name="txt" Text="{Binding itemname}" />
<Label Margin="0,-5,0,5" Style="{StaticResource ViewCellSecondaryLabelStyle}" x:Name="barcode" Text="{Binding productcode}" />
</StackLayout>
<Entry Margin="5,0,5,0" x:Name="quantity" Text="{Binding quantity}">
<Entry.BindingContext>
<ViewModel:AankoopEditViewModel />
</Entry.BindingContext>
</Entry>
<Image Margin="5,5,5,5" x:Name="delete" Source="{Mobile:ImageResource tbin_pos.png}">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path=BindingContext.DeleteCommand,Source={x:Reference Name=AankoopEditPage}}"
CommandParameter="{Binding}" />
</Image.GestureRecognizers>
</Image>
</ViewCell>
</DataTemplate>
</CustomControls:AutoLoadListView.ItemTemplate>
My Viewmodel:
public class AankoopEditViewModel : BaseViewModel
{
private VmPurchase Purchase;
public AankoopEditViewModel()
{
PurchaseList = new ReactiveObservableCollection<AankoopEditListItem>()
{
ChangeTrackingEnabled = true
};
this.WhenAnyValue(x => x.PurchaseID).SubscribeOn(RxApp.MainThreadScheduler).Subscribe((x) =>
{
this.Purchase = DatabaseHelper.Purchase.LoadSingleById<VmPurchase>(PurchaseID);
if (Purchase != null)
{
this.Title = Purchase.supplier.name;
using (PurchaseList.SuppressChangeNotifications())
{
foreach (var detail in Purchase.purchasedetails)
{
PurchaseList.Add(new AankoopEditListItem { productcode = detail.item.code, itemname = detail.item.namenl, identifier = detail.key, quantity = detail.quantity.ToString() });
}
}
}
});
try
{
this.WhenAnyValue(x => x.PurchaseList).SubscribeOn(RxApp.MainThreadScheduler).Subscribe((x) =>
{
Console.WriteLine("The List has changed");
});
}
catch (Exception e)
{
return;
}
}
private string _purchaseID;
public string PurchaseID
{
get { return _purchaseID; }
set { this.RaiseAndSetIfChanged(ref _purchaseID, value); }
}
private ReactiveObservableCollection<AankoopEditListItem> _purchases;
public ReactiveObservableCollection<AankoopEditListItem> PurchaseList
{
get
{
return this._purchases;
}
set
{
this.RaiseAndSetIfChanged(ref _purchases, value);
}
}
My Model :
public class AankoopEditListItem : ReactiveObject
{
public string identifier { get; set; }
public string itemname { get; set; }
public string productcode { get; set; }
public string quantity { get; set; }
}
Be careful, when you do this
<Entry.BindingContext>
<ViewModel:AankoopEditViewModel />
</Entry.BindingContext>
you create a new instance of your view model for each item and you bind your Entry to it. Just remove it and keep the binding as it is (Text="{Binding quantity}") if you want to bind your entry to the row view model

Bound observable collection update without 'RemoveOf' & 'Insert'

Currently I am trying to implement an observable collection which is bound to a data template (WPF-MVVM). During initialization it loads the default value to observable collection. Idea is:
User provides some value on the textbox,
presses ENTER key
increments a counter and updates the count value on textblock which is located near the text box.
The purpose is to track how times the text value has been changed by the user.
Right now it is working with 'IndexOf', 'RemoveAt' and 'Insert'. Is there a way to do without 'RemoveAt' and 'Insert'.
I feel something wrong on my code? Can anybody help it.
InputDataTemplate.xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Name}" />
<Label Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Count}" />
<TextBox x:Name="IpDataTb" Grid.Column="1" Width="60" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding}" Text="{Binding Path=Data, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<ei:CallMethodAction TargetObject="{Binding }" MethodName="IpDataTrig" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
TestView.xaml:
<UserControl.Resources>
<DataTemplate x:Key="InputDataTemplate" >
<local:InputDataTemplate DataContext="{Binding}" />
</DataTemplate>
</UserControl.Resources>
<Grid>
<Border BorderBrush="#FF0254B4" BorderThickness="1" >
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" >
<ItemsControl ItemsSource="{Binding InputDatas}"
ItemTemplate="{DynamicResource InputDataTemplate}" />
</ScrollViewer>
</Border>
</Grid>
DataService.cs:
using MyObsrCollTest.ViewModels;
namespace MyObsrCollTest.Services
{
public class InputDataService : BindableBase
{
public string Name { get; set; }
public string Count { get; set; }
public string Data { get; set; }
public void IpDataTrig(object sender,KeyEventArgs e)
{
var IpDataTb = new TextBox();
IpDataTb = (TextBox)sender;
if ((e.Key == Key.Enter) &&(!string.IsNullOrWhiteSpace(IpDataTb.Text)))
{
this.Data = IpDataTb.Text;
ObsrCollTestVm.TestMe(this.Name, this.Data);
}
}
}
}
ObsrCollTestVm.cs:
private ObservableCollection<InputDataService> _InputDatas;
static int _count = 0;
public ObsrCollTestVm(void)
{
for (int i = 0; i < 5; i++)
{
var l_InputDatas = new InputDataService();
l_InputDatas.Name = i.ToString();
l_InputDatas.Count = "0";
l_InputDatas.Data = "?";
_InputDatas.Add(l_InputDatas);
}
}
Basic initialization routine:
public ObservableCollection<InputDataService> InputDatas
{
get
{
if (_InputDatas == null)
{
_InputDatas = new ObservableCollection<InputDataService>();
}
return _InputDatas;
}
}
New Observable collection:
public static void TestMe(string name, string data)
{
var found = _InputDatas.FirstOrDefault(element = > element.Name == name);
if (found != null)
{
int i = _InputDatas.IndexOf(found);
found.Count = _count++;
_InputDatas.RemoveAt(i);
_InputDatas.Insert(i, found);
}
}
Increment the count value:
If I understand the question correctly, it can be summarized as:
"I would like to be able to change the Count property of my InputDataService class objects and have that change reflected in that item's Label, without having to modify the ObservableCollection<InputDataService> itself."
Is that correct?
If so, then the solution is for your InputDataService class to correctly provide notifications of property changes. Normally, this would mean either inheriting DependencyObject and implementing your properties as dependency properties, or just implementing the INotifyPropertyChanged interface.
But in your example, you seem to be inheriting a class named BindableBase already. If that class is in fact the Microsoft.Practices.Prism.Mvvm.BindableBase class, then it already implements INotifyPropertyChanged and all you need to do is take advantage of that.
For example:
public class InputDataService : BindableBase
{
private int _count;
public string Name { get; set; }
public int Count
{
get { return _count; }
set { SetProperty(ref _count, value); }
}
public string Data { get; set; }
public void IpDataTrig(object sender,KeyEventArgs e)
{
var IpDataTb = new TextBox();
IpDataTb = (TextBox)sender;
if ((e.Key == Key.Enter) &&(!string.IsNullOrWhiteSpace(IpDataTb.Text)))
{
this.Data = IpDataTb.Text;
ObsrCollTestVm.TestMe(this.Name, this.Data);
}
}
}
Notes:
In the above, I only fixed the issue for the Count property. You can apply similar changes to the other properties to get them to update correctly.
In your TestMe() method, you seem to be using the Count property as an int, but it was declared in your code example as a string. Lacking a better way to reconcile that discrepancy in your code example, I've just changed the property declaration in the example above to use int instead of string.
This example assumes you are using .NET 4.5, in which the [CallerMemberName] attribute is supported. If you're using an earlier version of .NET, then you will need to add the property name to the SetProperty() call. E.g.: SetProperty(ref _count, value, "Count");
With these changes, you should be able to write TestMe() like this:
public static void TestMe(string name, string data)
{
var found = _InputDatas.FirstOrDefault(element = > element.Name == name);
if (found != null)
{
found.Count = _count++;
}
}

Pulling data from Azure displaying on MainPage and ItemPage

I currently have the data for my application stored in an Azure Mobile Service SQL Database. I am pulling items from the database and displaying them in a List View. When a user clicks on an item in the list view they are then navigated to a new page that displays more details about the specific record from the database.
Main Page Code:
public class OSVersions
{
[JsonProperty(PropertyName = "id")]
public int id { get; set; }
[JsonProperty(PropertyName = "Version")]
public string Version { get; set; }
[JsonProperty(PropertyName = "Codename")]
public string Codename { get; set; }
[JsonProperty(PropertyName = "Publish")]
public bool Publish { get; set; }
[JsonProperty(PropertyName = "ReleaseDate")]
public DateTime ReleaseDate { get; set; }
[JsonProperty(PropertyName = "Changes")]
public string Changes { get; set; }
[JsonProperty(PropertyName = "Notes")]
public string Notes { get; set; }
}
public partial class OSMainVIew : PhoneApplicationPage
{
private MobileServiceCollection<OSVersions, OSVersions> items;
private IMobileServiceTable<OSVersions> osTable =
App.MobileService.GetTable<OSVersions>();
public OSMainVIew()
{
InitializeComponent();
}
private async void RefreshOSItems()
{
progressBar1.IsEnabled = true;
progressBar1.IsIndeterminate = true;
items = await osTable
.Where(OSItem => OSItem.Publish == true)
.ToCollectionAsync();
MainListBox.ItemsSource = items;
progressBar1.IsEnabled = false;
progressBar1.Visibility = System.Windows.Visibility.Collapsed;
progressBar1.IsIndeterminate = false;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
RefreshOSItems();
}
private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (MainListBox.SelectedIndex == -1)
return;
NavigationService.Navigate(new Uri("/ViewModels/OS/OSItemView.xaml?selectedItem=" + MainListBox.SelectedIndex, UriKind.Relative));
MainListBox.SelectedIndex = -1;
}
}
Item Page Code:
public partial class OSItemView : PhoneApplicationPage
{
private MobileServiceCollection<OSVersions, OSVersions> items;
private IMobileServiceTable<OSVersions> osTable =
App.MobileService.GetTable<OSVersions>();
public OSItemView()
{
InitializeComponent();
if ((Application.Current as App).IsTrial)
{
//textBlock1.Text = "Change Log available in full version only!";
//textBlock2.Visibility = System.Windows.Visibility.Collapsed;
}
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
string selectedIndex = "";
int buildID;
int idValue;
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
//Start progressBar
progressBar1.IsEnabled = true;
progressBar1.IsIndeterminate = true;
//Convert selectedIndex -> buildID
idValue = Convert.ToInt32(selectedIndex);
buildID = idValue + 1;
/* buildID = idValue + 1 becuase on OSMainView
* Items stored in the ListBox are each even an index number
* The first number is '0'
* This is a problem because the first IDNumber in the Database is '1'
* This isn't the best way to handle this, becuase even though the id field is an auto-increamental field,
* sometimes values are skipped and rows are deleted.
*/
//Query database
items = await osTable
.Where(OSItem => OSItem.id == buildID)
.ToCollectionAsync();
MainListBox.ItemsSource = items;
//End progressBar
progressBar1.IsEnabled = false;
progressBar1.Visibility = System.Windows.Visibility.Collapsed;
progressBar1.IsIndeterminate = false;
}
}
}
Items Page XAML Code:
<Grid x:Name="ContentPanel" Margin="10,97,12,0" Grid.RowSpan="2">
<ListBox x:Name="MainListBox" Margin="10,-35,-12,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,0" Width="432" Height="*">
<TextBlock TextWrapping="Wrap" Text="{Binding Version}" Style=" {StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="Notes" FontFamily="Segoe WP Bold" Foreground="{StaticResource PhoneAccentBrush}" Height="30" HorizontalAlignment="Left" Margin="0,1,0,0" Name="textBlock3" Padding="0" VerticalAlignment="Top" Width="444" />
<TextBlock x:Name="notesText" Text="{Binding Notes}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Height="180" VerticalAlignment="Top" HorizontalAlignment="Stretch" FontFamily="Segoe WP SemiLight" Margin="0" Width="455"/>
<TextBlock Text="Change Log" Height="30" HorizontalAlignment="Left" Margin="0,222,0,0" Name="textBlock1" VerticalAlignment="Top" FontFamily="Segoe WP Bold" Foreground="{StaticResource PhoneAccentBrush}" Width="444" Padding="0" />
<TextBlock Name="textBlock2" Text="{Binding Changes}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontFamily="Segoe WP SemiLight" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
My problem occurs when MainListBox.ItemsSource = items; is executed.
The application quits without any error codes.
Any ideas?
The problem had to due with the Height of the StackPanel being set to '*'. After removing that, the problem was solved.

Bind item-related variable to listheader in longlistselector (WP8)

I'm new to Windows Phone development and I'm currently facing an issue while using the LongListSelector in WP8, and I don't know how to proceed to achieve the result I want.
I use it to display a list of items as usual. The class used contains 5 items, and one of them is a float value. I want to display, in the list header, the sum of all positive float values contained in the list, but I have no idea whatsoever about how to do this.
I tried to bind another variable (result of the sum) specificly to the listheader in addition to the original binding, or to add another item in the class containing the sum result (hence repeated throughout the list in each list item), but it didn't work.
I guess this is a pretty basic fonctionnality (for instance to count and display the number of elements of the list), but I can't figure out how to do this.
EDIT : I thought showing my code wouldn't help, but here it is. (I took away the formatting that wasn't relevant)
XAML
<phone:LongListSelector x:Name="ListeSolde" LayoutMode="List">
<phone:LongListSelector.ListHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding SommeTotale}" />
</DataTemplate>
</phone:LongListSelector.ListHeaderTemplate>
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nom}" />
<TextBlock Text="{Binding DerniereConnexion}" />
<TextBlock Text="{Binding Depuis}" />
<TextBlock Text="{Binding Solde}" />
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Class definition
public class resume
{
public string Nom { get; set; }
public double Solde { get; set; }
public string Depuis { get; set; }
public string DerniereConnexion { get; set; }
public resume(string nom, double solde, string depuis, string derniereconnexion)
{
this.Nom = nom;
this.Solde = solde;
this.Depuis = depuis;
this.DerniereConnexion = derniereconnexion;
}
}
public class total
{
public double Total { get; set; }
public double calculTotal(List<resume> soldes)
{
double total = new double();
foreach (resume solde in soldes)
{
if (solde.Solde > 0)
total += solde.Solde;
}
return total;
}
public total(double Dtotal)
{
this.Total = Dtotal;
}
}
And code behind
public MainPage()
{
InitializeComponent();
List<resume> soldes = new List<resume>();
Donnees MainData = new Donnees();
soldes = MainData.RefreshResume(soldes); // A method that basically add items to the list
total SommeTotale = new total(1);
SommeTotale.Total = SommeTotale.calculTotal(soldes);
ListeSolde.ItemsSource = soldes;
}
This of course doesn't work (as far as the list header is concerned) and this is how I would do it
This is how I managed to bind other data from my ViewModel to the header of the LongListSelector.ListHeader.
<phone:LongListSelector.ListHeaderTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="2" Foreground="DarkViolet"
Text="{Binding ElementName=LayoutRoot, Path=DataContext.AddressBookList.Count}" />
</Grid>
</DataTemplate>
</phone:LongListSelector.ListHeaderTemplate>
The ListHeader property binds directly to the DataContext of the LongListSelector. This is different that the items contained within the LongListSelector. The items contained within it are bound to each item within the ItemSource. One of the best ways to get the ListHeader to display is to create an object that houses the data for the LongListSelector
public class ResumeContainer
{
public double SommeTotale { get { return Resumes.Sum(r => r.Value); } }
public IEnumerable<Resume> Resumes { get; set; }
}
You would set the DataContext of the LongListSelector to be an instance of the ResumeContainer. This would preferably be a property of your ViewModel. You would need to change your xaml to be
<phone:LongListSelector x:Name="ListeSolde" ItemsSource="{Binding Resumes}">
Your code-behind then changes to
List<resume> soldes = new List<resume>();
Donnees MainData = new Donnees();
soldes = MainData.RefreshResume(soldes);
ListeSolde.DataContext = new ResumeContainer { Resumes = soldes };

InvalidCastException when accessing a ListBox from codebehind

I have a listbox with the following xaml which filled from a XMLReader
<ListBox Name="listBox4" Height="498" SelectionChanged="listBox4_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Epon}" FontSize="32"/>
<TextBlock Text="{Binding Telnum}" FontSize="24" />
<TextBlock Text="{Binding Beruf}" FontSize="16" />
<TextBlock Text="{Binding Odos}" FontSize="16"/>
<TextBlock Text="{Binding Location}" FontSize="16"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to call the phone when i'll select the lisbox item so I created the following class
public class PhoneList
{
public string Epon { get; set; }
public string Telnum { get; set; }
public string Beruf { get; set; }
public string Odos { get; set; }
public string Location { get; set; }
public PhoneList(string Telnum, string Epon, string Beruf, string Odos, string Location)
{
this.Telnum = Telnum;
this.Epon = Epon;
this.Beruf = Beruf;
this.Odos = Odos;
this.Location = Location;
}
}
On the event of the selection which is below
private void listBox4_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
PhoneList nPhone = (PhoneList)listBox4.SelectedItem;
string mPhoneCopy = nPhone.Telnum;
string mNameCopy = nPhone.Epon;
var pt = new PhoneCallTask();
pt.DisplayName = mNameCopy;
pt.PhoneNumber = mPhoneCopy;
pt.Show();
}
I get the error InvalidCastException in the first line of the event.
What is causing this error?
From the XAML posted, there is not a collection bound to the ListBox. This either means there is no binding, or the binding is being set in the code behind. The following are merely shots in the dark since no additional code has been posted:
Properly Bind the ListBox
Assuming a collection is part of the DataContext, the collection will need to be bound to the ListBox:
<ListBox ItemsSource="{Binding Path=MyCollection}"... />
A starting resource: MSDN: How to: Bind to a Collection and Display Information Based on Selection
Verify the Object Before Casting
This may be the case where the item selected is empty, i.e., the first item in the list has no value. In that case, check to see if the object is the type you are expecting before doing anything else:
private void listBox4_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var nPhone = listBox4.SelectedItem as PhoneList;
if (nPhone == null)
{
return;
}
string mPhoneCopy = nPhone.Telnum;
string mNameCopy = nPhone.Epon;
var pt = new PhoneCallTask();
pt.DisplayName = mNameCopy;
pt.PhoneNumber = mPhoneCopy;
pt.Show();
}
Other Thoughts
I suspect that there may not be a collection bound to the ListBox`; perhaps there is supposed to be some code-behind to set the binding that isn't being executed?
In the end, if none of the above applies to your case, edit the post with the relevant code that is creating the collection and setting the collection as the ItemsSource of the ListBox.

Categories