Bounded element's ItemsSource is not updated in view - c#

I have a simple ListView What is bound to an object's (TaxonDescription) list.
When I select another TaxonDescription, then the ListView's element are doesnt updated.
Maybe I need somewhere the NotifyPropertyChanged, but i tried everywhere.
There are my classes.
At the page's codebehind I check the ItemSource, and it is have the right list element, just dont updated to the View.
<ListView ItemsSource="{Binding Descriptions}"
SelectedItem="{Binding ActualSelectedDescription, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DescriptionName}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
// this not updated
<ListView ItemsSource="{Binding ActualSelectedDescription.Images}">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding NormalUri}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock Text="{Binding ActualSelectedDescription.Name}"/> //This is works well
The ActualSelectedDescription is changed by an event.
public TaxonDescription ActualSelectedDescription
{
get{return actualSelectedDescription;}
set { actualSelectedDescription = value;
RaisePropertyChanged("ActualSelectedDescription"); }
//In the setter the Images are in the list
}
And there is the list element in the Images list
There is the Description class, with the list.
class TaxonDescription
{
public List<BaseImage> Images { get; private set; }
public string Name { get; private set; }
public TaxonDescription(string taxonName, string descriptionName)
{
Name = taxonName;
Images = new List<BaseImage>();
//Adding some element
}
}
Any accurate idea can help, i will try them all ;)

ActualSelectedDescription.Images has no change notification.
Try adding notification for Images property.
If that's not possible, make Images an ObservableCollection<BaseImage>.
If that's an issue, try setting data context to a notifying property:
// this should start updating
<ListView DataContext="{Binding ActualSelectedDescription}"
ItemsSource="{Binding Images}">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding NormalUri}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
EDIT:
Just noticed that TaxonDescription is not public - is that a typo here in SO or is the class private in your actual code?
Since if it's private, the ItemsSource="{Binding ActualSelectedDescription.Images}" will not work since there's no access to Images property.

Related

TextBlock not showing up in ListView

This is my ListView:
<ListView ItemsSource="{Binding ModuleList}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<Image Source="{Binding ModuleImage}" Stretch="UniformToFill"/>-->
<TextBlock Text="{Binding ModuleName}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is the code in WPF (MVVM):
public ItemListViewVM() : base()
{
ModuleList = new List<Module>();
modulLoader.LoadAllModules();
tempModulList = modulLoader.GetAllModules();
foreach (var module in tempModulList)
{
ModuleImage = module.ModuleImage;
ModuleName = module.Name;
ModuleList.Add(module);
}
}
Long story short: The List tempModulList contains Objects of type Module, which has an ImageSource Image and a string Name. Then the ModuleList gets one item after another. When I uncomment the Image in xaml, you can see it. But the TextBlock won't show up no matter what. I checked the string module.Namefor every item, it is not empty.
EDIT: Add Module Class
The Module Class just contains Name and Image:
public class Module
{
public ImageSource ModuleImage { get; set; }
public string Name { get; set; }
}
The Object gets created by deserializing a Json
The Bindings in the ItemTemplate use the properties of the data item class as their source properties. Hence you should write
Text="{Binding Name}"
instead of
Text="{Binding ModuleName}"
Unless you set the View property of a ListView (to e.g. a GridView) you could also better use a ListBox, which is the base class of ListView, and simpler:
<ListBox ItemsSource="{Binding ModuleList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ModuleImage}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Initializing the ModuleList property in the view model constructor would be as simple as this:
public ItemListViewVM()
{
modulLoader.LoadAllModules();
ModuleList = modulLoader.GetAllModules();
}

binding to a static list and properties xamarin forms

I am making a portable Xamarin project. I have the following List in the class Stash:
public class Stash
{
public static List<Group> Groups { get; set; }
}
and a class Group:
public class Group
{
[JsonProperty(PropertyName ="Name")]
public string Name { get; set; }
[Newtonsoft.Json.JsonProperty("Id")]
public string GroupId { get; set; }
}
In another page in XAML I want to bind to a static list. I have a ListView that I want to bind to the Group List:
<ListView ItemsSource="{Binding Source={x:Static local:Stash.Groups}}"
IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" TextColor="Black"
Detail="{Binding GroupId}" DetailColor="Aqua">
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I defined the Namespace in the local in XAML:
xmlns:local="clr-namespace:Namespace"
My List is filled from the Sql Azure Database so it is not empty guys , Can anybody tell me what is wrong with my code? I cant seem to display the list on my screen , All what is displayed is this sentence Namespace.Group .
The following binding is incorrect. You don't need to
<ListView ItemsSource="{Binding Source={x:Static local:Stash.Groups}}"
You should change this to
<ListView ItemsSource="{Binding {x:Static local:Stash.Groups}"
Databinding Xamarin ListView
its working , i just removed IsGroupingEnabled="true" and it worked
<ListView ItemsSource="{Binding Source={x:Static local:Stash.Groups}}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" TextColor="Black"
Detail="{Binding GroupId}" DetailColor="Aqua">
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>

Binding in ListBox using MVVM

I have a problem binding all array entries to my ListBox in XAML.
XAML:
<ListBox ItemsSource="{Binding ResultFlag}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TypeInfo}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ResultFlag property in my ViewModel (which is the DataContext of the XAML file):
private ObservableCollection<DataField> _resultFlag;
public ObservableCollection<DataField> ResultFlag
{
get { return _resultFlag; }
set
{
_resultFlag = value;
OnPropertyChanged();
}
}
TypeInfo in the DataField class:
public string[] TypeInfo { get; set; }
I would like to show all string entries from above array in the ListBox - how should I do this? I've tried several things including nested Listbox and binding the ItemsSource of the ListBox directly to the array (didn't work, BTW)
Cheers!
What you have in your scenario is a List of List. In order to show that in your list box you need to have nested ListBoxes like this.
<ListBox ItemsSource="{Binding ResultFlag}" >
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding TypeInfo}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Binding Hierarchical TreeView To Dictionary

I'm trying to get my TreeView to bind to a Dictionary that will be updated. I've implemented INotifyProperyChangedHandler on the data type itself, but will this effect the treeview at all?
What I'm aiming for is:
-FolderName
--->Item1
--->Item2
-FolderName
--->Item1
This is my View:
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="ChildTemplate" >
<TextBlock FontStyle="Italic" Text="{Binding Path=m_Items}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="NameTemplate"
ItemsSource="{Binding Path=Value}"
ItemTemplate="{StaticResource ChildTemplate}">
<TextBlock Foreground="White" Text="{Binding m_Name}" FontWeight="Bold" />
</HierarchicalDataTemplate>
</UserControl.Resources>
<TreeView x:Name="NewTree" ItemsSource="{Binding m_FolderList, UpdateSourceTrigger=PropertyChanged}" ItemTemplate="{StaticResource NameTemplate}">
</TreeView>
My ViewModel:
public Dictionary<UInt16, Folder> m_FolderList
{
get { return Manager.Instance.GetFolderDirectory(); }
}
My Folder class:
public class Folder
{
public m_Name { get; set; }
public ObservableCollection<String> m_Items { get; set; }
}
What I'm getting is a blank treeview that never updates. Whenever I add a new item to the "FolderDirectory" in that singleton manager instance, I do an OnPropertyChanged call. Which works for anything else I've been binding to that dictionary or Folder item.
I was trying to follow this, but how the binding observes that it automatically childrens the "FamilyMembers" list escapes me because nowhere do you explicitly tell the XAML template that it should bind itemsource to that collection. http://www.wpf-tutorial.com/treeview-control/treeview-data-binding-multiple-templates/
EDIT:
The control is definitely getting all the values from my singleton. I just was playing around with the naming of the Binding Path and when I accidentally set the TreeView to bind to m_FolderList.Value (dictionaries have Values, not just Value), it gave me as many binding errors in the console as there were Items in the dictionary.
EDIT2:
public List<Folder> m_FolderList
{
get
{
List<Folder> list = new List<Folder>();
list.AddRange(Manager.Instace.GetFolderDirectory().Values);
return list;
}
}
If I do this, instead of Dictionary, the first Level of information appears... Which is a nuisance
Try this
<Window.Resources>
<DataTemplate x:Key="secondLevel">
<TextBlock Text="{Binding}"/>
</DataTemplate>
<HierarchicalDataTemplate x:Key="topLevel" ItemsSource="{Binding Value.m_Items}" ItemTemplate="{StaticResource secondLevel}">
<TextBlock Text="{Binding Value.m_Name}">
</TextBlock>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel>
<TreeView x:Name="FolderTree" ItemsSource="{Binding m_FolderList}" ItemTemplate="{StaticResource topLevel}">
</TreeView>
</StackPanel>
output
public List<Folder> m_FolderList
{
get
{
List<Folder> list = new List<Process>();
list.AddRange(Manager.Instance.GetFolderDirectory().Values);
return list;
}
}
I hate doing this, but its the only method that worked here with the Heirarchical template. I've used a binding to dictionary Path=Value before numerous times but it just refused to work in this instance with many attempts. Its not the best answer, but its the only working one I have at the moment.

MVVM + multilevel/nested databinding

The Structure
The scenario is that I have a Pivot where each item is the menu of a certain day. Inside that PivotItem I need to display the dishes on the menu, grouped by category (e.g. soups, desserts, ...).
I have implemented this with the MVVM-model.
I thus have the folowing models:
public class Menu{
public string Date;
public List<DishList> Categories;
}
public class DishList
{
public string Category;
public List<Dish> Dishes;
}
public class Dish
{
public string Name;
public string Price;
}
Edit: these are simplified here, the actual structure for each field is like this:
private string _date;
//Get_Set
public string Date
{
get
{
return _date;
}
set
{
if (value != _date)
{
_date = value;
}
}
}
So the structure would be like this: a PivotElement containt a Menu-object. Inside it, I show Categories, a number of DishLists. Inside that Dishlist, I show the Category and the different Dishes, each with it's Name and Price. A mockup to make things a bit more clear (pdf-file on SkyDrive); http://sdrv.ms/12IKlWd
I have the following viewmodel
public class MenuViewModel : INotifyPropertyChanged
{
private ObservableCollection<Menu> _Menus;
}
The view that should implement (the structure) of the desired layout is as following:
<phone:Pivot
ItemsSource="{Binding Menus}">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Date}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ItemsControl
ItemsSource="{Binding Categories}">
<TextBlock
Text="{Binding Category}"/>
<ItemsControl
x:Name="Dishes"
ItemsSource="{Binding Dishes}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="1"
Text="{Binding Name}"/>
<TextBlock
Grid.Column="2"
Text="{Binding Price}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ItemsControl>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
As you can see, there's nested databinding to get to the data it needs.
The only code I then do on the page is
DataContext = App.ViewModel;
The Problem
When I launch it up, I get the correct Data displayed in the PivotItems header, and the correct number of PivotItems. Ufortunately, that's it; the content of the PivotItem stays empty. The first level of databinding thus works, but no further.
The way I was thinking
1st level: each PivotItem is linked to an object of type Menu, with header Menu.Date
2nd level: Inside that PivotItem I set the ItemsSource of a ItemsControl to that Menu.Categories
3rd level : The ItemsSource now is Menu.Categories.Dishes
I have already searched quite a bit and fiddled around with Datacontext and ItemsSource and different kinds of "{Binding ...}", but I can't get it to work. I would like to do the binding in xaml, and not in the code-behind.
Notes
The only function is to display data. The data is stationary and loaded once from a file.
That's why I chose ItemsControl instead of ListBox, there is no need to select anything.
This is a MVVM-approach to my previous question: Databinding + Dynamic Pivot
First off, you're trying to access a private field in the title so that won't work. These also have to be properties, not fields.
<TextBlock Text="{Binding Date}" />
private string Date;
Next you're binding to Category, which is also private and not a property.
<TextBlock Text="{Binding Category}"/>
private string Category;
And you're binding to the Categories field which needs to be a property.
<ItemsControl ItemsSource="{Binding Categories}">
public List<DishList> Categories;
Even if you correct these issues, you still won't get what you want because your outer ItemsControl doesn't have an ItemTemplate.
<ItemsControl ItemsSource="{Binding Categories}">
<TextBlock Text="{Binding Category}"/>
...
</ItemsControl>
Added: Your new error is because the DataTemplate can only have one child element so you need to use a container like a StackPanel.
<ItemsControl ItemsSource="{Binding Categories}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Category}"/>
<ItemsControl x:Name="Dishes" ItemsSource="{Binding Dishes}">
...
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Categories