I am trying to make a grouped gridview in Windows 8 application I have a class named book whose ObservableCollection I have made in my ViewModel class for that page. But I need to group the data when I am trying to group and bind the data on my codebind file of XAML and then binding there is no effect of INotifyProperty happening. Please suggest how can I achieve this in my VW?
Code Below:
Code Behind of XAML:
protected override void LoadState(Object navigationParameter,
Dictionary<String, Object> pageState)
{
MainViewModel booksList = new MainViewModel();
var teamGroups = booksList.BooksDetail.GroupBy(team => team.BookCategory)
.OrderBy(team => team.Key.ToString());
this.groupedItemsViewSource.Source = teamGroups;
}
View Model Class:
#region BooksDetail Collection
/// <summary>
/// The <see cref="BooksDetail" /> BooksDetail
/// </summary>
public const string BooksDetailPropertyName = "BooksDetail";
private ObservableCollection<Book> _booksDetailProperty = new ObservableCollection<Book>();
/// <summary>
/// Gets the BooksDetail property.
/// TODO Update documentation:
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the Messenger's default instance when it changes.
/// </summary>
public ObservableCollection<Book> BooksDetail
{
get
{
return _booksDetailProperty;
}
set
{
if (_booksDetailProperty == value)
{
return;
}
_booksDetailProperty = value;
// Update bindings, no broadcast
RaisePropertyChanged(BooksDetailPropertyName);
}
}
#endregion
public void GetBooksDetail()
{
try
{
// Check if the code is in Design Mode or Running Mode
if (ViewModelBase.IsInDesignModeStatic)
{
// Created the object of main model class
DesignMainModel mainModel = new DesignMainModel();
// Call method to get list of books detail
this.BooksDetail = mainModel.GetBooksDetailData();
}
else
{
// Check for internet connectivity
if (Utility.IsInternetAvailable())
{
//TODO: Write the logic to to implement in Running Mode
// Created the object of main model class
DesignMainModel mainModel = new DesignMainModel();
// Call method to get list of books detail
this.BooksDetail = mainModel.GetBooksDetailData();
// Group by data on Book Category
this.GroupByBookDetailsOnCategory();
}
else
{
// Display Error Message for No internet Connection available
util.ShowUserMessage(App.GeneralMessageResource.GetString("InternetConnectionErrorMessage"), App.GeneralMessageResource.GetString("InternetConnectionErrorCategory"));
}
}
}
catch (Exception ex)
{
// Display the error
util.ShowUserMessage(ex.Message, App.GeneralMessageResource.GetString("GeneralErrorTitle"));
}
}
}
Books Class:
#region BookCategory Property
/// <summary>
/// The <see cref="BookCategory" /> property's name.
/// </summary>
public const string BookCategoryPropertyName = "BookCategory";
/// <summary>
/// The _book category property
/// </summary>
private string _bookCategoryProperty = string.Empty;
/// <summary>
/// Gets the BookCategory property.
/// TODO Update documentation:
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the Messenger's default instance when it changes.
/// </summary>
public string BookCategory
{
get
{
return _bookCategoryProperty;
}
set
{
if (_bookCategoryProperty == value)
{
return;
}
_bookCategoryProperty = value;
// Update bindings, no broadcast
RaisePropertyChanged(BookCategoryPropertyName);
}
}
#endregion
Changed as per the input: I have created an ObservableCollection of Tuple. But now when I am binding it to CollectionViewSource then no list is getting populated. Please refer the code below: Let me know where I am making mistake:
XAML:
<GridView Grid.Row="1" Margin="5,0,0,0" Grid.Column="1"
x:Name="itemGridView"
SelectionMode="Multiple"
ItemTemplate="{StaticResource CategoryLists}"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemContainerStyle="{StaticResource CategoryListsStyle}">
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" Margin="15,0,0,0">
<TextBlock Text="{Binding Key}" Margin="0,-5,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" FontFamily="Segoe UI Regular" Foreground="#00bfff" FontSize="27"/>
<!--<TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol" Margin="0,-7,0,10" Style="{StaticResource GroupHeaderTextStyle}"/>-->
</StackPanel>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="10,-1,35,0"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</Grid>
Property: #region BooksDetailGrouped Collection /// /// The property's name. /// public const string BooksDetailGroupedPropertyName = "BooksDetailGrouped";
/// <summary>
/// The _books detail grouped property
/// </summary>
private ObservableCollection<Tuple<string, ObservableCollection<Book>>> _booksDetailGroupedProperty = new ObservableCollection<Tuple<string, ObservableCollection<Book>>>();
/// <summary>
/// Gets the BooksDetailGrouped property.
/// TODO Update documentation:
/// Changes to that property's value raise the PropertyChanged event.
/// This property's value is broadcasted by the Messenger's default instance when it changes.
/// </summary>
public ObservableCollection<Tuple<string, ObservableCollection<Book>>> BooksDetailGrouped
{
get
{
return _booksDetailGroupedProperty;
}
set
{
if (_booksDetailGroupedProperty == value)
{
return;
}
_booksDetailGroupedProperty = value;
// Update bindings, no broadcast
RaisePropertyChanged(BooksDetailGroupedPropertyName);
}
}
#endregion
Method to group:
// Grouping the data
var booksGroup = this.BooksDetail.GroupBy(books => books.BookCategory)
.OrderBy(books => books.Key.ToString());
// Convert grouped data to ObservableCollection<Tuple<string, ObservableCollection<Book>>>
this.BooksDetailGrouped = new ObservableCollection<Tuple<string, ObservableCollection<Book>>>(
booksGroup.Select(x => Tuple.Create(x.Key,
new ObservableCollection<Book>(x))));
You simply do not have an observable collection bound to your grid.
in this line
var teamGroups = booksList.BooksDetail.GroupBy(team => team.BookCategory)
.OrderBy(team => team.Key.ToString());
you create a linq statement that wraps your observable collection and exposes IOrderedEnumerable
which you bind to your view. And this interface obviously does not forward change events from your collection and your property.
To solve this you need to hold in your BooksDetails
(or any other property in your view model) ObservableCollection
that is already sorted and grouped and bind it directly in xaml. Setting source in this maner:
this.groupedItemsViewSource.Source = booksList.BooksDetail;
will not allow grid to recreate it self when BooksDetail
property is changed.
var observableCollection = new ObservableCollection<Tuple<Key, ObservableCollection<Book>>>(
teamGroups.Select(x=>Tuple.Create(x.Key,
new ObservableCollection<Book>(x))));
If you want to crate second property note that you will have to synchronize them when books are added, deleted or have category changed.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.