Listbox Binding With No Results Listed - xaml

I have a Windows Phone App and I am trying to bind an ObservableCollection to a Listbox to list, at the moment, strings. However when I run the app nothing is listed and I cannot see where I am going wrong.
XAML:
<ListBox ItemsSource="{Binding EventList}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Black" FontSize="20"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code-Behind:
private ObservableCollection<String> eventList = new ObservableCollection<String>();
public ObservableCollection<String> EventList
{
get { return eventList; }
}
public MainPage()
{
eventList.Add("Event One");
eventList.Add("Event Two");
eventList.Add("Event Three");
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}

Have you set the DataContext of your main page to the application class that has EventList as a property? Set a break point on your get accessor and check if it is being called. If not, then you need to set the DataContext.

Related

ListView selected Item binding not work

I have a listview in uwp , and a view model that declare pataient_List and selected_patient in this. my listview show itemsource but I don't know why my listview do not show selected item.
<ListView ItemsSource="{Binding pataient_List}"
SelectedItem="{Binding selected_patient, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding name_to_show_menu, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
viewmodel is
public class patient_view_model : notify_property_changed_base
{
public patient_view_model(patient patient_param)
{
pataient_List = new ObservableCollection<patient>();
load_patient(); // this function put patients in pataient_List
selected_patient = patient_param;
}
public patient selected_patient
{
get { return _selected_patient; }
set
{
if (_selected_patient != value)
{
_selected_patient = value;
RasiePropertyChanged();
}
}
}
public ObservableCollection<patient> pataient_List { set; get; }
One cause could be that the selected item must be one of the objects in the pataient_List.
Another cause is perhaps because you're setting the selected_patient in the constructor of the view model which is definitely before you bind the view model to the view. So, why not trying to set the selected_patient after you bind the view model to the view.
Forget about the ItemTemplate in the ListView.
<ListView ItemsSource="{Binding pataient_List}"
SelectedItem="{Binding selected_patient, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="Black">
</ListView>
.NET doesn't have a clue about how you want your data to be displayed, so it just calls the ToString() method on each object and uses that to represent the item. Override the ToString() method in the patient object to display what you need. Here is the code:
public class patient
{
public string name_to_show_menu;
public override string ToString()
{
return this.name_to_show_menu;
}
}
I solve issue with this one answer.
public override bool Equals(object obj)
{
if (this.name_to_show_menu == (obj as patient).name_to_show_menu)
return true;
else
return false;
}

XAML ListView in ListView

Is it possible to make a ListViewin a ListView and if yes is it even possible to bind data in both of them? I already tried it but it wont work the first List is shown as i want but the second is not shown.
The Code Looks kind of like this:
<ListView ItemSource="{Binding Item}" x:Name="ListA">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Day}"/>
<ListView x:Name="ListB" ItemSoruce="{Binding Item}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Time}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
listA.ItemsSource = timebooking.TimeBookingDataPeriod.TimeBookingData;
Hope sombody can help me :)
First of all, you should either go for a binding ItemSource={Binding Item} or setting the ItemSource in code listA.ItemsSource = ... as one overwrites the other. So I'll ignore the fact that you're trying to set it in code and go with the binding (which means you have a datacontext set on your view).
<ListView ItemSource="{Binding WeekDays}" x:Name="ListA">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Day}"/>
<ListView x:Name="ListB" ItemSource="{Binding TimesOfDay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Time}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I've changed your first ItemSource to WeekDays and the second ItemSource to TimesOfDay for clarity. This to explain the way how binding and datacontexts work.
The outer ListView (ListA) inherits its DataContext from the outer items, most likely your page / usercontrol.
In your ListViewItem, the datacontext is changed to a single item in the WeekDays collection. => every property bound under this tree has to be in a WeekDay object.
The inner ListView (ListB) inherits its DataContext from the ListViewItem.
In the ListViewItem, the DataContext is changed to a single item in the TimesOfDay collection.
Every ListView is a new level of objects. So for my sample to work, you need following class structure, not that I'll simplify the code and just use properties (while you should correctly implement INotifyPropertyChanged for UI updates).
public class SampleViewModel : INotifyPropertyChanged
{
public ObservableCollection<WeekDay> WeekDays { get; set; } // first listview
}
public class WeekDay
{
public string Day { get; set; }
public ObservableCollection<TimeOfDay> TimesOfDay { get; set; } // second listview
}
public class TimeOfDay
{
public string Time { get; set; }
}
If you want to use 2 properties from the page's viewmodel, you'll have to use an element binding in ListB. But this is only for scenarios were the items in the inner listview are not correlated to the ones in the outer listview.
{Binding ElementName=ListA, Path=DataContext.ItemsForB}
ItemsSource not ItemSource
Here is an example:
public class ClassB
{
public string Name { get; set; }
public ObservableCollection<ClassA>classAList { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ClassB"/> class.
/// </summary>
public ClassB()
{
Name = String.Empty;
classAList = new ObservableCollection<ClassA>();
}
}
public class ClassA
{
public string Caption { get; set; }
}
Create list:
ObservableCollection<ClassB> list = new ObservableCollection<ClassB>();
Init list:
ClassB item1 = new ClassB() { Name = "listAItem1" };
item1.classAList.Add(new ClassA { Caption = "listBItem1" });
item1.classAList.Add(new ClassA { Caption = "listBItem2" });
item1.classAList.Add(new ClassA { Caption = "listBItem3" });
item1.classAList.Add(new ClassA { Caption = "listBItem4" });
item1.classAList.Add(new ClassA { Caption = "listBItem5" });
list.Add(item1);
ClassB item2 = new ClassB() { Name = "listAItem1" };
item2.classAList.Add(new ClassA { Caption = "listBItem1" });
item2.classAList.Add(new ClassA { Caption = "listBItem2" });
item2.classAList.Add(new ClassA { Caption = "listBItem3" });
item2.classAList.Add(new ClassA { Caption = "listBItem4" });
item2.classAList.Add(new ClassA { Caption = "listBItem5" });
list.Add(item1);
this.DataContext = list;
and XAML:
<ListView ItemsSource="{Binding}" x:Name="ListA">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="Day"/>
<ListView x:Name="ListB" ItemsSource="{Binding classAList}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Caption}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It seems you want to create a grouped list, in this case is better to use gridview with groups:
Good step by step tutorial for grouped gridview

How to get access to text from all the textboxes( where textboxes are created dynamically) in windows phone runtime

I have been trying to get texts from the collection of textboxes which are created dynamically by binding a collection to a stackpanel using items control which is in seperate user control which i am loading on a page in windows phone runtime.
Below is the code of my UserControl:
<UserControl
x:Class="CfMobility.UserControls.CredentialsUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CfMobility.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding SelectedCategorySettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel IsTapEnabled="False">
<TextBlock Text="{Binding SettingKey}" Style="{ThemeResource BaseTextBlockStyle}"></TextBlock>
<TextBox Text="{Binding SettingValue}" Width="300px"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
I have a Content control in another page as below:
<ContentControl x:Name="Container" Grid.Row="1" Margin="19,10,19,0">
</ContentControl>
Where i am binding this content control to above stackpanel when i am navigating to the page.
As You can see i had bonded "SelectedCategorySettings" collection to StackPanel using ItemsScroll which displays number of text boxes based on the collecion. Here i am unable to figure out if i want to save text from all the text boxes which are displayed on the page into a json file, how to access the text of all the text boxes which are dynamically displayed in above scenario?
PS: note that items is control is in a separate user control.
Thanks in Advance
You should use ObservableCollection for SelectedCategorySettings and your model class which contains SettingKey and SettingValue should implement INotifyPropertyChanged interface as in following example code. If you do it correctly then whatever the changes happen in UI (in your case, text changes of textbox) will automatically reflect in your model objects in the ObservableCollection. If you are interested to learn more about how this works, I recommend you to search about mvvm design pattern in Windows Phone development.
public class Setting : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _settingKey;
public string SettingKey
{
get { return _settingKey; }
set {
_settingKey = value;
OnPropertyChanged("SettingKey");
}
}
private string _settingValue;
public string SettingValue
{
get { return _settingValue; }
set {
_settingValue = value;
OnPropertyChanged("SettingValue");
}
}
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
What you need is a method like this:
var textBoxes = AllTextBoxes(this);
public List<TextBox> AllTextBoxes(DependencyObject parent)
{
var list = new List<TextBox>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is TextBox)
{
list.Add(child as Control);
continue;
}
list.AddRange(AllChildren(child));
}
return list;
}

Different ItemSources for Panorama TitleTemplate, HeaderTemplate and ItemTemplate

I have a Panorama that has ItemSource set to an ObservableCollection which is created in the viewmodel
In the ViewModel.cs
public ObservableCollection<UserSchema> SeriesData;
private string _HeaderTitle;
public string HeaderTitle
{
get
{
return _HeaderTitle;
}
private set
{
_HeaderTitle = value;
NotifyPropertyChanged("HeaderTitle");
}
}
The value from HeaderTitle comes from HeaderSchema class's Title property (see below). This is set elsewhere in the viewmodel constructor not shown here.
UserSchema.cs contains the UserSchema which has implemented INotifyProperyChanged and has two properties. I have implemented the public getter and setter
private string _objectname;
private string _objectpath;
public string ObjectName
{
get
{
return _objectName;
}
set
{
_objectName = value;
NotifyPropertyChanged("ObjectName");
}
}
Similar code for _objectPath property also.
I have another HeaderSchema.cs that has also implemented INotifyProperyChanged and has two properties. I have implemented the public getter and setter
private string _Title;
public string Title
{
get
{
return _Title;
}
set
{
_Title = value;
NotifyPropertyChanged("Title");
}
}
Once again I have created a public get and set property for above as Title
Now in MainPage.xaml I have set the Panaroma ItemSource to SeriesData, elsewhere in the code behind I have set the DataContext to the viewmodel.
<controls:Panorama x:Name="SerPan" ItemsSource="{Binding SeriesData}">
<controls:Panorama.HeaderTemplate>
<DataTemplate>
<Grid x:Name="grid">
<TextBlock Text="{Binding ObjectName}">
</TextBlock>
</Grid>
</DataTemplate>
</controls:Panorama.HeaderTemplate>
<controls:Panorama.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ObjectPath}"/>
</DataTemplate>
</controls:Panorama.ItemTemplate>
</controls:Panorama>
This works very well and I get the correct output.
What I would like is to set a Title to the Panorama and I want to get the text from HeaderTitle property from viewmodel.
Something like the below, but the problem is HeaderTitle is a different property and not part of SeriesData which is the ItemSource for panorama.
<controls:Panorama.TitleTemplate>
<DataTemplate>
<TextBlock Text="{Binding HeaderTitle}"> //does not work.
</TextBlock>
</DataTemplate>
</controls:Panorama.TitleTemplate>
If your ViewModel is the DataContext of your Panorama control you can access it via ElementName Binding:
SerPan.DataContext = myViewModelInstance;
<phone:Panorama.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementName=SerPan, Path=DataContext.HeaderTitle}" />
</DataTemplate>
</phone:Panorama.HeaderTemplate>

Crash When Reordering Items in a ListView (Windows Store App using XAML)

I have an app that uses nested list views bound to ObservableCollections. The parent list views are used for grouping items, and each group contains a ListView of items. I used ListViews and ObservableCollections because I wanted users to be able reorder the groups, and also reorder the items within the group. I do not need them to move items between groups, though I may try that later. (:
The problem is after you reorder a group, if you try and drag an item out of the re-ordered group onto another group the app will crash in Windows.UI.XML.dll, and I can't for the life of me figure out how to prevent it. I don't want people to do that, but I also need it to not crash if they try.
I was able to reproduce this using a very lightweight app.
This is the class with the ObservableCollections:
public class GroupList
{
public ObservableCollection<Group> Groups { get; set; }
public GroupList()
{
Groups = new ObservableCollection<Group>();
Group group1 = new Group("Group 1");
group1.Items.Add(new Item("Item 1"));
group1.Items.Add(new Item("Item 2"));
group1.Items.Add(new Item("Item 3"));
Groups.Add(group1);
Group group2 = new Group("Group 2");
group2.Items.Add(new Item("Item 4"));
group2.Items.Add(new Item("Item 5"));
group2.Items.Add(new Item("Item 6"));
Groups.Add(group2);
Group group3 = new Group("Group 3");
group3.Items.Add(new Item("Item 7"));
group3.Items.Add(new Item("Item 8"));
group3.Items.Add(new Item("Item 9"));
Groups.Add(group3);
}
}
public class Group
{
public string GroupName { get; set; }
public ObservableCollection<Item> Items { get; set; }
public Group(string groupName)
{
this.GroupName = groupName;
this.Items = new ObservableCollection<Item>();
}
}
public class Item
{
public event PropertyChangedEventHandler PropertyChanged = null;
public string ItemName { get; set; }
public Item(string itemName)
{
this.ItemName = itemName;
}
}
This is the XAML for the page:
<Grid Background="White">
<ListView Name="groupListView" ItemsSource="{Binding}" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Red" Text="{Binding GroupName}"/>
</Border>
<ListView Name="itemListView" ItemsSource="{Binding Items}" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Blue" Text="{Binding ItemName}"/>
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
And this is the code-behind for the page:
public sealed partial class MainPage : Page
{
private GroupList groupList = new GroupList();
public MainPage()
{
InitializeComponent();
groupListView.DataContext = groupList.Groups;
}
}
To reproduce this issue:
1. Run the app
2. Drag and drop Group 1 between Group 2 and Group 3
3. Drag Item 1 from Group 1 onto Group 2
You should see a crash.
I have been pulling my hair out for hours trying different methods to prevent this from happening. The closest I came was handling the Drop event and setting Handled=true, but it would then still crash if you dropped it onto one of the group headers. If anyone can help me figure this out I would greatly appreciate it!
Thank you,
Todd