I'm trying to populate the Longlist via WCF following this tutorial. I want to group users by their income (from min to max), but groups are displayed randomly. Also there are no items in the list (see picture below). What am I missing?
My XAML code is:
<phone:PhoneApplicationPage.Resources>
<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
<DataTemplate x:Key="usersHeaderTemplate">
<Border Width="72" Height="72" HorizontalAlignment="Left" Background="{Binding Converter={StaticResource BackgroundConverter}}" Margin="6">
<TextBlock Text="{Binding Income}"
FontSize="20" Padding="6"
VerticalAlignment="Center" HorizontalAlignment="Center"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}" />
</Border>
</DataTemplate>
<DataTemplate x:Key="usersItemTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Flag}" Height="50" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextSubtleStyle}" />
<TextBlock Text="{Binding Income,StringFormat='Income: {0}'}" />
<TextBlock Text="{Binding Job}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<Style x:Key="LongListSelectorJumpListStyle" TargetType="phone:LongListSelector">
<Setter Property="GridCellSize" Value="113,113"/>
<Setter Property="LayoutMode" Value="Grid" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource BackgroundConverter}}"
Width="113" Height="113" Margin="6" >
<TextBlock Text="{Binding Title}"
FontFamily="{StaticResource PhoneFontFamilySemiBold}"
FontSize="48" Padding="6"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="usersListHeader">
<Border Background="White" Opacity="0.2" Height="70">
<TextBlock Text="List Header" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black" />
</Border>
</DataTemplate>
<DataTemplate x:Key="usersListFooter">
<Border Background="White" Opacity="0.2" Height="70">
<TextBlock Text="List Footer" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
</Border>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector x:Name="longlist2" Height="608" Margin="10,15,24,0" VerticalAlignment="Top" Width="422"
IsGroupingEnabled="True" LayoutMode="List" HideEmptyGroups="False"
ItemTemplate="{StaticResource usersItemTemplate}"
GroupHeaderTemplate="{StaticResource usersHeaderTemplate}"
JumpListStyle="{StaticResource LongListSelectorJumpListStyle}"
ListHeaderTemplate="{StaticResource usersListHeader}"
ListFooterTemplate="{StaticResource usersListFooter}" >
</phone:LongListSelector>
</Grid>
</Grid>
My service implementation is:
public IEnumerable<mTeachers> GetStuffList(string Job)
{
List<mTeachers> stuffList = new List<mTeachers>();
DataClasses1DataContext data = new DataClasses1DataContext();
List<mTeachers> finalList = new List<mTeachers>();
foreach (var d in data.Stuffs)
{
stuffList.Add(new mTeachers() { Name = d.stuffName, Income = (int)d.stuffIncome, Job = Job, Flag = new Uri(#"/Assets/users.png", UriKind.Relative) });
}
return stuffList;
}
private List<Group<mTeachers>> GetUsersGroups(string Job)
{
IEnumerable<mTeachers> usersList = GetStuffList(Job);
return GetItemGroups(usersList, c => c.Income);
}
private static List<Group<T>> GetItemGroups<T>(IEnumerable<T> itemList, Func<T, int> getKeyFunc)
{
IEnumerable<Group<T>> groupList = from item in itemList
group item by getKeyFunc(item) into g
orderby g.Key
select new Group<T>(g.Key, g);
return groupList.ToList();
}
public class Group<T> : List<T>
{
public Group(int income, IEnumerable<T> items)
: base(items)
{
this.Income = income;
}
public int Income
{
get;
set;
}
}
My service interface:
[OperationContract]
IEnumerable<mTeachers> GetStuffList(string Job);
}
[DataContract]
public class mTeachers
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Income { get; set; }
[DataMember]
public string Job { get; set; }
[DataMember]
public System.Uri Flag { get; set; }
}
EDIT: WP page code:
public MainPage()
{
InitializeComponent();
ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();
proxy.GetStuffListCompleted += showList;
proxy.GetStuffListAsync("teacher");
}
private void showList(object sender, ServiceReference1.GetStuffListCompletedEventArgs e)
{
this.longlist2.ItemsSource = e.Result;
}
Add ItemsSource="{Binding}" to the LongListSelector declaration in your XAML. So it should look like this.
<phone:LongListSelector x:Name="longlist2" Height="608" Margin="10,15,24,0" VerticalAlignment="Top" Width="422"
IsGroupingEnabled="True" LayoutMode="List" HideEmptyGroups="False"
ItemTemplate="{StaticResource usersItemTemplate}"
GroupHeaderTemplate="{StaticResource usersHeaderTemplate}"
JumpListStyle="{StaticResource LongListSelectorJumpListStyle}"
ListHeaderTemplate="{StaticResource usersListHeader}"
ListFooterTemplate="{StaticResource usersListFooter}"
ItemsSource="{Binding}" >
</phone:LongListSelector>
I think there are two things going on here.
First I think your GetStuffList(string Job) function is doing something weird, please check the return values to see if it's exactly what you want.
Second I think the ItemSource needs to be set like KasunKV said.
Here are my fixes and the resulting screenshot showing it works.
// create a static group list to see if it works
private List<Group<mTeachers>> GetUsersGroups(string Job)
{
List<mTeachers> usersList = new List<mTeachers>();
usersList.Add(new mTeachers() { Name = "Bob", Income = 1000, Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Guy" });
usersList.Add(new mTeachers() { Name = "Dan", Income = 1000, Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Guy" });
usersList.Add(new mTeachers() { Name = "Kate", Income = 2000, Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Girl" });
usersList.Add(new mTeachers() { Name = "Charlie", Income = 2000, Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Guy" });
usersList.Add(new mTeachers() { Name = "Jeff", Income = 2000, Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Guy" });
usersList.Add(new mTeachers() { Name = "Jeff2", Flag = new Uri(#"/Assets/AlignmentGrid.png", UriKind.Relative), Job = "Guy" });
return GetItemGroups(usersList, c => c.Income);
}
// Constructor
public MainPage()
{
InitializeComponent();
// create the user group and bind it to item source
this.longlist2.ItemsSource = GetUsersGroups("whatever");
}
Results of the change can be view here:
Related
How can I make the dropdown sub-items clickable? i.e if I click on 'Employees' it will open the Employees page. I copied this from a tutorial however they didn't explain how to make click events with this creation.
Subitem Class
public class SubItem
{
public SubItem(string name, UserControl screen = null)
{
Name = name;
Screen = screen;
}
public string Name { get; private set; }
public UserControl Screen { get; private set; }
}
}
ItemMenu Class
public class ItemMenu
{
public ItemMenu(string header, List subItems, PackIconKind icon)
{
Header = header;
SubItems = subItems;
Icon = icon;
}
public ItemMenu(string header, UserControl screen, PackIconKind icon)
{
Header = header;
Screen = screen;
Icon = icon;
}
public string Header { get; private set; }
public PackIconKind Icon { get; private set; }
public List<SubItem> SubItems { get; private set; }
public UserControl Screen { get; private set; }
}
}
**UserControlMenuItem.xaml**
<Grid>
<materialDesign:PackIcon Kind="{Binding Path=Icon}" Width="15" Height="15" Margin="10 16" Foreground="White"/>
<ListBoxItem x:Name="ListViewItemMenu" Content="{Binding Path=Header}" Padding="37 14" FontSize="15" Foreground="White"/>
<Expander x:Name="ExpanderMenu" Header="{Binding Path=Header}" IsExpanded="False" Width="210" HorizontalAlignment="Right" Background="{x:Null}" Foreground="White">
<ListView x:Name="ListViewMenu" ItemsSource="{Binding Path=SubItems}" Foreground="White" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Padding="20 5"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
</Grid>
**MainWindow.xaml**
<materialDesign:ColorZone Mode="PrimaryMid" Grid.ColumnSpan="2" HorizontalAlignment="Stretch">
<Grid>
<materialDesign:PopupBox PlacementMode="BottomAndAlignRightEdges" HorizontalAlignment="Right" Margin="10"/>
</Grid>
</materialDesign:ColorZone>
<Grid HorizontalAlignment="Stretch" Grid.Row="1" Background="{StaticResource PrimaryHueMidBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="326*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="GhostWhite">
<Image Source="Images/logo.png"/>
</Grid>
<ScrollViewer HorizontalAlignment="Stretch" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Grid.Row="1">
<StackPanel x:Name="Menu" Margin="10" />
</ScrollViewer>
</Grid>
<Frame Source="/CSA;component/Pages/Landing.xaml" Grid.Row="1" x:Name="ContentFrame" Grid.Column="1" Grid.ColumnSpan="2" Grid.RowSpan="2" Background="#2C2F33" Opacity="0.85" NavigationUIVisibility="Hidden" />
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var menuRegister = new List<SubItem>();
menuRegister.Add(new SubItem("Customer"));
menuRegister.Add(new SubItem("Providers"));
menuRegister.Add(new SubItem("Employees"));
menuRegister.Add(new SubItem("Products"));
var item6 = new ItemMenu("Register", menuRegister, PackIconKind.Register);
var menuSchedule = new List<SubItem>();
menuSchedule.Add(new SubItem("Services"));
menuSchedule.Add(new SubItem("Meetings"));
var item1 = new ItemMenu("Appointments", menuSchedule, PackIconKind.Schedule);
var menuReports = new List<SubItem>();
menuReports.Add(new SubItem("Customers"));
menuReports.Add(new SubItem("Providers"));
menuReports.Add(new SubItem("Products"));
menuReports.Add(new SubItem("Stock"));
menuReports.Add(new SubItem("Sales"));
var item2 = new ItemMenu("Reports", menuReports, PackIconKind.FileReport);
var menuExpenses = new List<SubItem>();
menuExpenses.Add(new SubItem("Fixed"));
menuExpenses.Add(new SubItem("Variable"));
var item3 = new ItemMenu("Expenses", menuExpenses, PackIconKind.ShoppingBasket);
var menuFinancial = new List<SubItem>();
menuFinancial.Add(new SubItem("Cash flow"));
var item4 = new ItemMenu("Financial", menuFinancial, PackIconKind.ScaleBalance);
var item0 = new ItemMenu("Dashboard", new UserControl(), PackIconKind.ViewDashboard);
Menu.Children.Add(new UserControlMenuItem(item0));
Menu.Children.Add(new UserControlMenuItem(item6));
Menu.Children.Add(new UserControlMenuItem(item1));
Menu.Children.Add(new UserControlMenuItem(item2));
Menu.Children.Add(new UserControlMenuItem(item3));
Menu.Children.Add(new UserControlMenuItem(item4));
}
```
All you need is to make the thing in ListView's ItemTemplate clickable. The easiest way to do that is to use a Button instead of a TextBlock. You can disable the Button's background and border to make it appear like text, but remain clickable.
Also, you don't need to use a ListView within an Expander. ListView offers scrolling capabilities and you don't need that. An ItemsControl will be enough.
Here's an example:
<Expander
Header="Expand me">
<ItemsControl ItemsSource="{Binding SubItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Background="Transparent"
BorderThickness="0"
Command="{Binding DataContext.DoSomethingCommand, ElementName=ThisWindow}"
Content="{Binding Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
I'm binding to the same ICommand for all the sub items in this example. Realisticly, you would either pass a CommandParameter as well for the different sub items or bind to a different command per item.
After hours of searching the web I found a solution.
Method
public static void Navigate(object target)
{
((MainWindow)Application.Current.Windows[0]).ContentFrame.Content = target;
}
Implementation
switch (Globals.PageName)
{
case "Landing":
Pages.Landing itemZ = new Pages.Landing();
Navigate(itemZ);
break;
case "ClientAcquisition":
Pages.ClientAcquisition item = new Pages.ClientAcquisition();
Navigate(item);
break;
I have a such XAML defined:
<UserControl x:Class="auditsListTest.AuditsList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:auditsListTest"
xmlns:local2="clr-namespace:auditsTest"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate DataType="local2:AnomalyComplex">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<TextBlock DockPanel.Dock="Left"
Text="{Binding Value.Description}" />
<ComboBox DockPanel.Dock="Right">
<ComboBoxItem Content="Fix" />
<ComboBoxItem Content="Fix 2" />
</ComboBox>
<Image DockPanel.Dock="Right"/>
<Button DockPanel.Dock="Right">
<TextBlock Text="Allow" />
</Button>
</DockPanel>
<ListBox ItemsSource="{Binding Value.GroupDescriptions}">
<ListBoxItem>
<DataTemplate>
<Expander Header="{Binding Key}" >
<DataTemplate>
<ListBox ItemsSource="{Binding Value}" />
</DataTemplate>
</Expander>
</DataTemplate>
</ListBoxItem>
</ListBox>
</DockPanel>
</DataTemplate>
<DataTemplate DataType="local2:AnomalyStandard">
<DockPanel DockPanel.Dock="Top">
<TextBlock DockPanel.Dock="Left"
Text="{Binding Value.Description}" />
<ComboBox DockPanel.Dock="Right">
<ComboBoxItem Content="Fix" />
<ComboBoxItem Content="Fix 2" />
</ComboBox>
<Image DockPanel.Dock="Right" />
<Button DockPanel.Dock="Right">
<TextBlock Text="Allow" />
</Button>
<TextBlock DockPanel.Dock="Bottom"
Text="{Binding Value.DescriptionDetailed}" />
</DockPanel>
</DataTemplate>
</UserControl.Resources>
<DockPanel Background="#FFA6FDE9">
<TextBlock DockPanel.Dock="Top">Kontrolka audits</TextBlock>
<ItemsControl HorizontalContentAlignment="Stretch"
x:Name="Tree"
DockPanel.Dock="Top"
ItemsSource="{Binding Anomalies}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Name="expander"
Loaded="expander_Loaded" IsExpanded="True" >
<Expander.HeaderTemplate>
<DataTemplate>
<DockPanel LastChildFill="True"
HorizontalAlignment="Stretch">
<TextBlock DockPanel.Dock="Left"
Text="{Binding Key}" />
<TextBlock DockPanel.Dock="Right"
HorizontalAlignment="Right">
<Run Text="Issues " />
<Run Text="{Binding Value.Count}" />
</TextBlock>
</DockPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<ContentControl>
<ItemsControl ItemsSource="{Binding Value}" />
</ContentControl>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</UserControl>
with below code-behind:
public partial class AuditsList : UserControl
{
public List<Anomaly> anomalies { get; set; }
public Lookup<string, Anomaly> groupedAnomalies { get; set; }
public List<KeyValuePair<string, List<Anomaly>>> groupedAnomalies2 { get; set; }
public AuditsList()
{
groupedAnomalies2 = ReturnData();
DataContext = new
{
Anomalies = groupedAnomalies2
};
InitializeComponent();
}
private List<KeyValuePair<string, List<Anomaly>>> ReturnData()
{
List<KeyValuePair<string, List<Anomaly>>> aaa = new List<KeyValuePair<string, List<Anomaly>>>();
Slide sld1 = new Slide();
sld1.Name = "slide1";
sld1.SlideIndex = 1;
Slide sld2 = new Slide();
sld1.Name = "slide2";
sld1.SlideIndex = 2;
Slide sld3 = new Slide();
sld1.Name = "slide3";
sld1.SlideIndex = 3;
Audit au1 = new Audit();
au1.Description = "desc1";
au1.Name = "audit1";
au1.Priority = 1;
Audit au2 = new Audit();
au2.Description = "desc2";
au2.Name = "audit2";
au2.Priority = 2;
List<string> descs1 = new List<string>();
descs1.Add("Wlazł kotek na płotek");
descs1.Add("Ala ma kota");
KeyValuePair<string, List<string>> kvp1 = new KeyValuePair<string, List<string>>("Polski", descs1);
List<string> descs2 = new List<string>();
descs2.Add("Good morning captain!");
descs2.Add("Fly! Fly! Fly away!");
KeyValuePair<string, List<string>> kvp2 = new KeyValuePair<string, List<string>>("English", descs2);
List<string> descs3 = new List<string>();
descs3.Add("keine scheise!");
descs3.Add("spreche dreche");
KeyValuePair<string, List<string>> kvp3 = new KeyValuePair<string, List<string>>("Deutsch", descs1);
AnomalyComplex ano1 = new AnomalyComplex();
ano1.Audit = au1;
ano1.Name = au1.Name;
ano1.Description = au1.Name;
ano1.Slide = sld1;
ano1.GroupDescriptions = new List<KeyValuePair<string, List<string>>>();
ano1.GroupDescriptions.Add(kvp1);
ano1.GroupDescriptions.Add(kvp2);
ano1.GroupDescriptions.Add(kvp3);
AnomalyStandard ano2 = new AnomalyStandard();
ano2.Audit = au2;
ano2.Name = au2.Name;
ano2.Slide = sld2;
ano2.DescriptionDetailed = "trele morele";
ano2.Description = au2.Name;
AnomalyStandard ano3 = new AnomalyStandard();
ano3.Audit = au2;
ano3.Name = au2.Name;
ano3.Slide = sld3;
ano3.Description = au2.Name;
ano3.DescriptionDetailed = "bomba trąba";
anomalies = new List<Anomaly>();
anomalies.Add(ano1);
anomalies.Add(ano2);
anomalies.Add(ano3);
groupedAnomalies = (Lookup<string, Anomaly>)anomalies.OrderBy(c => c.Audit.Priority).ToLookup(c => c.Audit.Priority == 1 ? "Slide " + c.Slide.SlideIndex.ToString() : "Presentation");
aaa = groupedAnomalies.Select(c => new KeyValuePair<string, List<Anomaly>>(c.Key, c.ToList())).ToList();
return aaa;
}
}
I have also defined below classes:
namespace auditsListTest
{
public class Slide
{
public int SlideIndex { get; set; }
public string Name { get; set; }
}
}
public class Audit
{
public string Name { get; set; }
public string Description { get; set; }
public int Priority { get; set; }
public virtual List<Anomaly> PerformAudit(double progress)
{
return new List<Anomaly>();
}
}
public class Anomaly
{
public string Name { get; set; }
public Audit Audit { get; set; }
public string Description { get; set; }
public bool Fixed { get; set; }
public bool Allowed { get; set; }
public string Container { get; set; }
public Slide Slide { get; set; }
public void Fix()
{
Fixed = true;
}
public void Allow()
{
Allowed = true;
}
}
public class AnomalyComplex : Anomaly
{
public List<KeyValuePair<string, List<string>>> GroupDescriptions { get; set; }
}
public class AnomalyStandard : Anomaly
{
public string DescriptionDetailed { get; set; }
}
What is the problem? First, textblocks with binding defined in Expander.HeaderTemplate are not showing values.
<TextBlock DockPanel.Dock="Left"
Text="{Binding Key}" />
<TextBlock DockPanel.Dock="Right"
HorizontalAlignment="Right">
<Run Text="Issues " />
<Run Text="{Binding Value.Count}" />
Second problem is with datatemplates with datatypes (DataType="local2:AnomalyComplex" and DataType="local2:AnomalyStandard") that are not automatically used. Should I use DataTemplateSelectors?
<ContentControl>
<ItemsControl ItemsSource="{Binding Value}" />
</ContentControl>
Could you analyze code and let me know where is problem, and how to solve it? Thanks in advance.
First, textblocks with binding defined in Expander.HeaderTemplate are not showing values.
Bind the Header property to the KeyValuePair<string, List<Anomaly>>:
<Expander Name="expander" Header="{Binding}">
<Expander.HeaderTemplate>
<DataTemplate>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<TextBlock DockPanel.Dock="Left" Text="{Binding Key}" />
<TextBlock DockPanel.Dock="Right" HorizontalAlignment="Right">
<Run Text="Issues " />
<Run Text="{Binding Value.Count, Mode=OneTime}" />
</TextBlock>
</DockPanel>
</DataTemplate>
</Expander.HeaderTemplate>
...
</Expander>
In case of DataTemplates with specified DataTypes, it should be specified inside curly braces, for example:
<DataTemplate DataType="{x:Type local2:AnomalyComplex}">
<DataTemplate DataType="{x:Type local2:AnomalyStandard}">
I need some advice. I have two ListViews first ListView is "ListViewAlbums" and the second "ListViewTracks".
Items in ListViewTracks are organized into groups.
ListViewAlbums is set SelectionMode = "Extended" and Behaviours: MultiSelectorBehaviours.SynchronizedSelectedItems.
MultiSelectorBehaviours
When I select multiple items from ListViewAlbums, so I want to show all the items in ListViewTracks based ALBUMID.
My current code:
ListViewTracks GroupDescriptions:
PropertyGroupDescription groupDescription = new PropertyGroupDescription("AlbumID");
viewTrack.GroupDescriptions.Add(groupDescription);
viewTrack.SortDescriptions.Add(new System.ComponentModel.SortDescription("AlbumTitle", System.ComponentModel.ListSortDirection.Ascending));
viewTrack.SortDescriptions.Add(new System.ComponentModel.SortDescription("TitleTrack", System.ComponentModel.ListSortDirection.Ascending));
Employees data:
private ObservableCollection<EmployeesAlbums> _listAlbums = new ObservableCollection<EmployeesAlbums>();
public ObservableCollection<EmployeesTracks> _listTrack = new ObservableCollection<EmployeesTracks>();
public ObservableCollection<EmployeesTracks> PlayListTracks
{
get { return _listTrack; }
set { _listTrack = value; RaisePropertyChanged("PlayListTracks"); }
}
public ObservableCollection<EmployeesAlbums> PlayListAlbums
{
get { return _listAlbums; }
set { _listAlbums = value; RaisePropertyChanged("PlayListAlbums"); }
}
EmployeesAlbums model = new EmployeesAlbums
{
IdAlbums = int.Parse(rdr["Id"].ToString()),
TitleAlbum = rdr["TitleAlbums"].ToString(),
ArtistAlbum = rdr["ArtistAlbums"].ToString()
};
modelTracks = new EmployeesTracks
{
IdTrack = int.Parse(rdr["Id"].ToString()),
TitleTrack = rdr["TitleTrack"].ToString(),
PathTrack = rdr["Path"].ToString(),
AlbumTitle = rdr["AlbumTitle"].ToString(),
ArtistTrack = rdr["ArtistTrack"].ToString(),
AlbumID = int.Parse(rdr["AlbumId"].ToString()).ToString()
};
SelectedItem of ListViewAlbums:
SelectionChangedItemsAlbumCommand = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(SelectionChangedItemsAlbum);
private EmployeesAlbums _selectedPlayListFileAlbum;
public EmployeesAlbums SelectedPlayListFileAlbum
{
get { return _selectedPlayListFileAlbum; }
set
{
if (_selectedPlayListFileAlbum != value)
{
_selectedPlayListFileAlbum = value;
RaisePropertyChanged("SelectedPlayListFileAlbum");
}
}
}
private IEnumerable<EmployeesAlbums> _selectedPlayListFilesAlbums;
public IEnumerable<EmployeesAlbums> SelectedPlayListFilesAlbums
{
get { return this.selectedPlayListFilesAlbums; }
set { Set(ref selectedPlayListFilesAlbums, value); }
}
Filtering:
public string AlbumID { get; set; }
void SelectionChangedItemsAlbum()
{
foreach (var items in SelectedPlayListFilesAlbums)
{
ListCollectionView empView = CollectionViewSource.GetDefaultView(PlayListTracks) as ListCollectionView;
// Enable Live Filtering of the ListViewCollection
empView.IsLiveFiltering = true;
// Enable the filtering on AlbumID
empView.LiveFilteringProperties.Add("AlbumID");
AlbumID = items.IdAlbums.ToString();
// Filter based upon AlbumID
empView.Filter = new Predicate<object>(IsMatchFoundAlbums);
// Refresh Collection
empView.Refresh();
}
}
bool IsMatchFoundAlbums(object d)
{
bool res = false;
EmployeesTracks emp = d as EmployeesTracks;
if (emp.AlbumID == AlbumID)
{
res = true;
}
return res;
}
XAML Code:
<ListView x:Name="ListViewTracks"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingStackPanel.CacheLength="20,20"
VirtualizingStackPanel.CacheLengthUnit="Item"
ItemsSource="{Binding PlayListTracks}"
Style="{StaticResource CommonListViewStyleTracks}"
ItemContainerStyle="{DynamicResource styleListViewItem}"
>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" />
<ItemsPresenter Margin="0,0,0,20" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate >
<Grid d:DesignWidth="460" Height="51">
<StackPanel>
<TextBlock DataContext="{Binding Items}" Text="{Binding AlbumTitle}" FontSize="18" TextTrimming="CharacterEllipsis" Foreground="{DynamicResource ItemsListViewForeground}"/>
<TextBlock DataContext="{Binding Items}" Text="{Binding ArtistTrack}" TextTrimming="CharacterEllipsis" Foreground="{DynamicResource AccentColorApps}"/>
</StackPanel>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
<ListView
x:Name="ListViewAlbums"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding PlayListAlbums}"
SelectionMode="Extended"
SelectedItem="{Binding SelectedPlayListFileAlbum,UpdateSourceTrigger=PropertyChanged}" SelectionMode="Extended"
behaviours:MultiSelectorBehaviours.SynchronizedSelectedItems="{Binding SelectedPlayListFilesAlbums, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Background="{x:Null}" Grid.Column="1" Grid.RowSpan="4"
ItemTemplate="{DynamicResource AlbumsDataTemplate}"
BorderBrush="{x:Null}"
>
<ie:Interaction.Triggers >
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding SelectionChangedItemsAlbumCommand}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</ListView>
Thanks a lot.
Try this
Right after you have initialized the property PlaylistTracks, do:
ListCollectionView empView = CollectionViewSource.GetDefaultView(PlayListTracks) as ListCollectionView;
empView.Filter = IsMatchFoundAlbums;
And let your Match method be:
bool IsMatchFoundAlbums(object d)
{
EmployeesTracks emp = d as EmployeesTracks;
return SelectedPlayListFilesAlbums.Any(x => x.IdAlbums == emp.AlbumID);
}
I have been having a problem with getting the exact value from the stackpanel.
XAML
<Page
x:Class="MedicinesApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MedicinesApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="MedicinesCollectionViewSource" IsSourceGrouped="True" />
</Page.Resources>
<GridView
ItemsSource="{Binding Source={StaticResource MedicinesCollectionViewSource}}"
x:Name="MedicinesGridView"
Padding="30,20,40,0"
SelectionMode="Single"
IsSwipeEnabled="false"
IsItemClickEnabled="True" SelectionChanged="MedicinesGridView_SelectionChanged"
ItemClick="MedicinesGridView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate x:Name="templateTrending">
<Grid HorizontalAlignment="Left" Width="250" Height="250" x:Name="wow">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Path=DiseaseImageSource}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<StackPanel Orientation="Vertical">
<TextBlock Text="Disease Name" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="30" Margin="15,0,15,0"/>
<TextBlock x:Name="DiseaseNameBro" Text="{Binding Path=DiseaseName, Mode=TwoWay}" Style="{StaticResource TitleTextBlockStyle}" Height="30" Margin="15,0,15,0"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock Text="Category of Disease" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,87,10"/>
<TextBlock Text="{Binding Path=CategoryOfDisease}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text='{Binding Key}' Foreground="Gray" Margin="5" FontSize="30" FontFamily="Segoe UI Light" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid MaximumRowsOrColumns="2" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
C#
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace MedicinesApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public string getMedicinesName;
public ObservableCollection<Disease> diseaseList = new ObservableCollection<Disease>();
public MainPage()
{
this.InitializeComponent();
diseaseList.Add(new Disease { DiseaseName = "Malaria", DiseaseImageSource = "/Assets/133px-Malaria.jpg", CategoryOfDisease = "Blood" });
diseaseList.Add(new Disease { DiseaseName = "Typhod", DiseaseImageSource = "../Assets/apple.jpg", CategoryOfDisease = "Thorat" });
diseaseList.Add(new Disease { DiseaseName = "Cancer", DiseaseImageSource = "../Assets/orange.jpg", CategoryOfDisease = "Body" });
diseaseList.Add(new Disease { DiseaseName = "Headache", DiseaseImageSource = "../Assets/bilberry.jpg", CategoryOfDisease = "Brain" });
//diseaseList = new ObservableCollection<Disease>(diseaseList.OrderBy(c => c.DiseaseName));
MedicinesCollectionViewSource.Source = GetGroupsByLetter();
}
internal List<GroupInfoList<object>> GetGroupsByLetter()
{
var groups = new List<GroupInfoList<object>>();
var query = from item in diseaseList
orderby item.DiseaseName
group item by item.DiseaseName[0] into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
var info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
public class GroupInfoList<T> : List<object>
{
public object Key { get; set; }
public new IEnumerator<object> GetEnumerator()
{
return base.GetEnumerator();
}
}
public class Disease
{
public string DiseaseName { get; set; }
public string DiseaseImageSource { get; set; }
public string CategoryOfDisease { get; set; }
}
private void MedicinesGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
getMedicinesName = ((Disease)MedicinesGridView.SelectedItem).DiseaseName;
}
private void MedicinesGridView_ItemClick(object sender, ItemClickEventArgs e)
{
this.Frame.Navigate(typeof(malaria), getMedicinesName);
}
}
the problem is whenever I click on Malaria,
it goes to the other page and shows cancer, which is the first vaule in the list.
How can I get the value of the item I click and not of the first item. I Have attached screenshot for you'll to get a better knowledge of things.
I looked at your code and there is one thing that I don't understand.
Why are you using 2 events to navigate. Only one would do the job.
private void MedicinesGridView_ItemClick(object sender, ItemClickEventArgs e)
{
var selectedDisease = e.ClickedItem as Disease;
this.Frame.Navigate(typeof(malaria), selectedDisease);
}
You don't need the getMedicinesName either.
Don't forget to remove the SelectionChanged event both from you code behind and XAML.
So, I am on my way learning MVVM Pattern for Windows Phone, and stuck how to bind the View to my ViewModel. App that I build now is getting current and next 5 days weather and display it to one of my panorama item on MainPage.xaml using UserControl.
I cannot just simply set the Forecasts.ItemsSource = forecast; in my WeatherViewModel, it says that Forecasts (Listbox element name in WeatherView) not exist in the current context.
Can anybody teach me how to bind it? and anybody have a good source/example sample to mvvm pattern in windows-phone? Thanks before.
EDIT:
WeatherModel.cs
namespace JendelaBogor.Models
{
public class WeatherModel
{
public string Date { get; set; }
public string ObservationTime { get; set; }
public string WeatherIconURL { get; set; }
public string Temperature { get; set; }
public string TempMaxC { get; set; }
public string TempMinC { get; set; }
public string Humidity { get; set; }
public string WindSpeedKmph { get; set; }
}
}
WeatherViewModel.cs
namespace JendelaBogor.ViewModels
{
public class WeatherViewModel : ViewModelBase
{
private string weatherURL = "http://free.worldweatheronline.com/feed/weather.ashx?q=";
private const string City = "Bogor,Indonesia";
private const string APIKey = "APIKEY";
private IList<WeatherModel> _forecasts;
public IList<WeatherModel> Forecasts
{
get
{
if (_forecasts == null)
{
_forecasts = new List<WeatherModel>();
}
return _forecasts;
}
private set
{
_forecasts = value;
if (value != _forecasts)
{
_forecasts = value;
this.NotifyPropertyChanged("Forecasts");
}
}
}
public WeatherViewModel()
{
WebClient downloader = new WebClient();
Uri uri = new Uri(weatherURL + City + "&num_of_days=5&extra=localObsTime&format=xml&key=" + APIKey, UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ForecastDownloaded);
downloader.DownloadStringAsync(uri);
}
private void ForecastDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("Cannot load Weather Forecast!");
}
else
{
XDocument document = XDocument.Parse(e.Result);
var current = from query in document.Descendants("current_condition")
select new WeatherModel
{
ObservationTime = DateTime.Parse((string)query.Element("localObsDateTime")).ToString("HH:mm tt"),
Temperature = (string)query.Element("temp_C"),
WeatherIconURL = (string)query.Element("weatherIconUrl"),
Humidity = (string)query.Element("humidity"),
WindSpeedKmph = (string)query.Element("windspeedKmph")
};
this.Forecasts = (from query in document.Descendants("weather")
select new WeatherModel
{
Date = DateTime.Parse((string)query.Element("date")).ToString("dddd"),
TempMaxC = (string)query.Element("tempMaxC"),
TempMinC = (string)query.Element("tempMinC"),
WeatherIconURL = (string)query.Element("weatherIconUrl")
}).ToList();
}
}
}
}
WeatherView.xaml
<UserControl x:Class="JendelaBogor.Views.WeatherView"
xmlns:vm="clr-namespace:JendelaBogor.ViewModels">
<UserControl.DataContext>
<vm:WeatherViewModel />
</UserControl.DataContext>
<Grid Margin="0,-10,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Current" Grid.Row="0" Height="150" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" delay:LowProfileImageLoader.UriSource="{Binding WeatherIconURL}" Width="120" Height="120" VerticalAlignment="Top"/>
<StackPanel Grid.Column="1" Height="200" VerticalAlignment="Top">
<TextBlock Text="{Binding Temperature}" FontSize="22"/>
<TextBlock Text="{Binding ObservationTime}" FontSize="22"/>
<TextBlock Text="{Binding Humidity}" FontSize="22"/>
<TextBlock Text="{Binding Windspeed}" FontSize="22"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1" Height="300" VerticalAlignment="Bottom" Margin="10,0,0,0">
<StackPanel VerticalAlignment="Top">
<StackPanel Height="40" Orientation="Horizontal" Margin="0,0,0,0">
<TextBlock Text="Date" FontSize="22" Width="170"/>
<TextBlock Text="FC" FontSize="22" Width="60"/>
<TextBlock Text="Max" TextAlignment="Right" FontSize="22" Width="90"/>
<TextBlock Text="Min" TextAlignment="Right" FontSize="22" Width="90"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<ListBox ItemsSource="{Binding Forecasts}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Height="40" Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Text="{Binding Date}" FontSize="22" TextAlignment="Left" Width="170" />
<Image delay:LowProfileImageLoader.UriSource="{Binding WeatherIconURL}" Width="40" Height="40" />
<TextBlock Text="{Binding TempMaxC, StringFormat='\{0\} °C'}" TextAlignment="Right" FontSize="22" Width="90" />
<TextBlock Text="{Binding TempMinC, StringFormat='\{0\} °C'}" TextAlignment="Right" FontSize="22" Width="90" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</UserControl>
MainPage.xaml
<controls:PanoramaItem x:Name="Weather" Header="weather">
<views:WeatherView />
</controls:PanoramaItem>
You need to tell the view what viewmodel you are using. By adding
<UserControl
xmlns:vm="clr-namespace:JendelaBogor.ViewModels">
<UserControl.DataContext>
<vm:WeatherViewModel />
</UserControl.DataContext>
</UserControl>
all {Binding}'s are mapped to the class WeatherViewModel. By using the ItemsSource property on the listbox as Reed suggests you can then bind all items from a list that you expose through a property.
If the list is ever changed while running the application, consider using an ObservableCollection and clearing it and adding all new items when new data is received. If you do, your GUI will simply update with it.
The ViewModel doesn't know about the view.
You need to make a Forecasts property on the ViewModel, and bind the ItemsSource to it from your View. In your view, change the ListBox to:
<!-- No need for a name - just add the binding -->
<ListBox ItemsSource="{Binding Forecasts}">
Then, in your ViewModel, add:
// Add a backing field
private IList<WeatherModel> forecasts;
// Add a property implementing INPC
public IList<WeatherModel> Forecasts
{
get { return forecasts; }
private set
{
forecasts = value;
this.RaisePropertyChanged("Forecasts");
}
}
You can then set this in your method:
this.Forecasts = (from query in document.Descendants("weather")
select new WeatherModel
{
Date = DateTime.Parse((string)query.Element("date")).ToString("dddd"),
TempMaxC = (string)query.Element("tempMaxC"),
TempMinC = (string)query.Element("tempMinC"),
WeatherIconURL = (string)query.Element("weatherIconUrl")
})
.ToList(); // Turn this into a List<T>