I'm trying to use a SemanticZoom in my Windows 8 application and it seems to not work.
Do I do something wrong here ?
I tried pretty much everything I thought that could work but in vain : removed the rowdefinitions, removed the style, removed the templates but still not working...
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<SemanticZoom Grid.RowSpan="2">
<SemanticZoom.ZoomedInView>
<GridView x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
SelectionMode="None"
IsSwipeEnabled="True"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource GridViewItemTemplateZoomIn}"
ItemsPanel="{StaticResource GridViewItemsPanelTemplate}"
helpers:ItemClickCommand.Command="{Binding ServiceClickCommand}">
<GridView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,10,6">
<Button AutomationProperties.Name="Group Title"
Style="{StaticResource TextPrimaryButtonStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
Margin="3,-7,10,10"
Style="{StaticResource GroupHeaderTextStyle}" />
<TextBlock Text="{StaticResource ChevronGlyph}"
FontFamily="Segoe UI Symbol"
Margin="0,-7,0,10"
Style="{StaticResource GroupHeaderTextStyle}" />
</StackPanel>
</Button>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"
Margin="0,0,80,0" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<GridView x:Name="itemZoomOutGridView"
ScrollViewer.IsHorizontalScrollChainingEnabled="False"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Padding="116,175,40,46"
SelectionMode="None"
IsSwipeEnabled="True"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource GridViewItemTemplateZoomOut}"
ItemsPanel="{StaticResource GridViewItemsPanelTemplate}"
ItemsSource="{Binding ServiceCategories}">
</GridView>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
Thank you :)
If I understand your problem correctly, the semanticView in itself is working (you can zoom in and zoom out). But when you zoom back in the GridView items are the same and doesn't change according to the ZoomedOutView GridView item you selected.
But with your XAML I think this is normal behaviour, because when you select a category the binding on your gridview in zoomedInView doesn't change.
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
My first advice would be to bind the ItemsSource to a list in your ViewModel not use a staticRessource.
Secondly you can change the SemanticView this way:
<SemanticZoom Grid.RowSpan="2" ViewChangeStarted="SemanticZoomChanged" >
And in your code behind add that:
private void SemanticZoomChanged(object sender, SemanticZoomViewChangedEventArgs e)
{
// First we check that we are going from ZoomedOut to ZoomedIn
if (e.IsSourceZoomedInView == false)
{
// I call a method in my ViewModel giving the chosen category in parameter
DefaultViewModel.OnSelectedCategoryChanged(e.SourceItem.Item.ToString());
}
}
Using MVVM I know it's ugly to have code in code-behind but this is not a lot and we are calling a method in the ViewModel to do the logic so it's still following MVVM design pattern.
And last we add a function in the ViewModel that will change the ItemsSource of the ZoomedInView
OnSelectedCategoryChanged(string chosenCategory)
{
// Here change the value of your groupedItemsViewSource list
GroupedItemsViewSource = ....;
}
Now it should work as you want to.
Related
I am working on a UWP application, trying to implement ItemClick event on a GridView, however, when I click on an Item, nothing happens.
The relevant code is below:
Book.xaml:
<Page.DataContext>
<vm:BookViewModel x:Name="ViewModel" />
</Page.DataContext>
<GridView Grid.Row="1"
Padding="18"
ItemsSource="{Binding Source={StaticResource BookViewSource}}"
IsItemClickEnabled="True"
ItemClick="{x:Bind ViewModel.BookGroups_OnItemClick}">
BookViewModel.cs:
public void NavigateToDetails(string url)
{
NavigationService.Navigate(typeof(Views.DetailPage), url);
}
public void BookGroups_OnItemClick(object sender, ItemClickEventArgs e)
{
var bookHeader = (BookGroup)e.ClickedItem;
NavigateToDetails(bookHeader.url);
}
I would really appreciate your help, thank you!
EDIT : Book.xaml GrdivView source:
<GridView Grid.Row="1"
Padding="18"
ItemsSource="{Binding Source={StaticResource BookViewSource}}"
IsItemClickEnabled="True"
ItemClick="{x:Bind ViewModel.BookGroups_OnItemClick}"
>
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="250" Height="250" >
<Border VerticalAlignment="Bottom" Background="#AA000000">
<TextBlock Text="{Binding name}" Margin="12" Foreground="White"/>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}" Margin="-12,0,0,0"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
I have copied your code 1:1 into a new project and the NavigateToDetails method does get called. Please try to put a breakpoint in the method to see if it gets hit. If it does, there might be a problem with the NavigationService. Otherwise, the problem is very likely in the GridView.ItemTemplate - it may be possible that there is a control that handles the click event so that it doesn't bubble up to the GridView at all.
So finally as I deleted the following part from Book.xaml, the item click works fine:
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}" Margin="-12,0,0,0"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
I did not find out what caused the problem, but now it works.
Thank you for your help and time :)
I am using a GridView ( and I even tried ListView for this purpose ) as a context indicator of my FlipView. The Problem is that when I try to tap/click on a gridViewItem in order for it to get selected and hence changing the flipviewItem index as well, the gridview is not recieving any tap or click interaction by the user to change it. However when I change flipviewItem from directly flipview, it works as expected and gridview item selected is also changed accordingly.
CODE
<Grid>
<FlipView x:Name="MainFlipView" ItemsSource="{x:Bind MyItemsSource}" Visibility="Visible"
SelectionChanged="FlipChanged">
<FlipView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<userControls:FlipDataTemplate />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
<GridView SelectionChanged="ContextChanged"
Name="ContextIndicator"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Margin="0,0,12,12"
ItemsSource="{x:Bind MyItemsSource}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<Image Width="40" Height="40" Source="{x:Bind Display}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
C#
private void FlipChanged(object sender, SelectionChangedEventArgs e)
{
ContextIndicator.SelectedIndex = MainFlipView.SelectedIndex;
}
private void ContextChanged(object sender, SelectionChangedEventArgs e)
{
MainFlipView.SelectedIndex = ContextIndicator.SelectedIndex;
}
You need to set IsItemClickEnabled to True on your GridView.
I was able to solve it with help of #JustinXL and I put FlipView and GridView in Rows and made RowSpan of FlipView to 2 so I got same UI as I wanted but now it works as expected, apparently if they are in same row then FlipView interferes with UI interaction on GridView.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<FlipView x:Name="MainFlipView" ItemsSource="{x:Bind MyItemsSource}" Visibility="Visible" Grid.RowSpan="2"
SelectionChanged="FlipChanged">
<FlipView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<userControls:FlipDataTemplate />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
<GridView SelectionChanged="ContextChanged" Grid.Row="1"
Name="ContextIndicator"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,12,8"
Canvas.ZIndex="1"
ItemsSource="{x:Bind MyItemsSource}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<Image Width="40" Height="40" Source="{x:Bind Display}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
I work on an app where the user can edit a "big" form:
The form contains a lot of fields: it is displayed in a Pivot, where each PivotItem represents a category of the form.
Some categories contain one or more child items: they are displayed through a Master-Detail presentation.
To display the items of the Detail part, I use a ContentPresenter that is binded directly to the Model:
<ContentPresenter
x:Name="DetailContentPresenter"
Grid.Column="1"
Grid.RowSpan="2"
BorderThickness="1,0,0,0"
Padding="24,0"
BorderBrush="{ThemeResource SystemControlForegroundBaseLowBrush}"
Content="{x:Bind MasterListView.SelectedItem, Mode=OneWay}">
<ContentPresenter.ContentTemplate>
<DataTemplate x:DataType="models:Form_Parts">
<...>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
This works fine, but there is a "third" level in the main form: a list of photos, that I display in the ContentPresenter through a GridView. This works also great, but I would like to use an "Add" button or the "ItemClick" event to interact with the photos: I don't see how I could bind a Command in the main ViewModel, instead of the ContentPresenter's DataContext. The other fields of this form bind well on this ViewModel.
I did some tests without any result:
<StackPanel Orientation="Horizontal" Grid.Row="1">
<GridView ItemsSource="{Binding images}"
ItemClick="{Binding PhotoClickCommand}">
<GridView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1"
Padding="10"
Height="150" Width="190">
<Image Stretch="UniformToFill"
Source="{Binding bitmap_image}" />
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Border BorderBrush="Gray" BorderThickness="1"
Padding="10"
Height="150" Width="190">
<Button Command="{Binding Path=DataContext.AddPhotoCommand, ElementName=DetailsPage}"
Height="100" Width="100">
<Viewbox>
<SymbolIcon Symbol="Add"/>
</Viewbox>
</Button>
</Border>
</StackPanel>
=> is there a way to doing this?
Edit :
I solved my problem for the "Add" button thanks Alteik with:
<Button Command="{Binding ElementName=Root, Path=DataContext.AddPhotoCommand}" Height="100" Width="100">
But I always get a problem with the ItemClick of the GridView. I tried this:
<GridView ItemsSource="{Binding images}"
IsItemClickEnabled="True"
SelectionMode="None">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=Root, Path=DataContext.EditPhotoCommand}"
CommandParameter="{Binding Mode=OneWay}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
<...>
</GridView>
But I don't get the expected parameter in the ViewModel:
private void EditPhoto(object sender)
{
Images sImage = (Images)sender;
if (sImage != null)
{
NavigationService.NavigateTo<CommentImageViewModel>(this, new Object[] { sImage }, true);
}
}
The sender is the current Form_Parts (the DataTemplate of the ContentPresenter), whereas I would get the selected item of my images collection, that is binded to the GridView...
=> Whad could I do to fix this?
You should be able to change the DataContext in a child element doing this:
Command"{Binding ElementName=Root, Path=DataContext.TheCommandFromRoot}"
Obviously you need to set the name of the parent's element to "Root"
I need to create a vertical scrolling list view with grouping enabled as shown below:
This is what I currently have:
<common:VariableSizeListViewWithSelection ItemsSource="{Binding Source={StaticResource cvs}}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
IsItemClickEnabled="True"
ItemTemplateSelector="{StaticResource summaryViewTemplateSelector}" >
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="0,0,0,2">
<TextBlock Grid.Column="0" Text="{Binding Title}" Margin="0,-11,10,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" FontWeight="SemiBold" Foreground="#333333" />
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
<common:VariableSizeListViewWithSelection.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="LightGray" Margin="0">
<TextBlock Text='{Binding Title}' Foreground="Black" Margin="5" Style="{StaticResource HeaderTextBlockStyle}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" Width="300" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</common:VariableSizeListViewWithSelection.GroupStyle>
</common:VariableSizeListViewWithSelection>
But this is not working as expected and it creates a listview with correct grouping but with just one column like this:
Can you please point me as to what am I doing wrong?
We took it offline for a bit and it seems like changing the ItemsPanel of the ListView to a StackPanel make this work. I have a feeling the default ItemsStackPanel should still support grouping, but perhaps not with a custom group layout panel. Maybe there is a way to reconfigure a GridView to scroll vertically and this could work too.
I finally got my pivot control to work using MVVM in a wp8 app but I still have a question in regards to binding as thought as it works, and I could accept it as is, I'm not happy with the outcome and I'm trying to understand why this is happening. My DataContext, MainViewModel, contains multiple other ViewModels.
Scenario 1:
If I define the DataContext in the Grid (layout), and I assign the itemsSource for the pivot headers to QuickSearchTabs ViewModel and this get built ok but the listbox I have defined inside the pivotitem doesn't which is assigned the QuickSearchButtons ViewModel doesn't get built. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource MainViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" FontSize="{StaticResource PhoneFontSizeSmall}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}">
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
Scenario 2:
If I define the DataContext in the Grid (layout) and define the same DataContext within the listbox tags, it will build my header and my listbox BUT it will call my viewModel which is assigned to the ItemsSource of the listbox, multiple times. To be exact, it will call it the same number of time as the number of pivots I have. Here is the xaml code:
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource CriteriaViewModel}" >
<phone:Pivot x:Name="Pivot" ItemsSource="{Binding QuickSearchTabs}" SelectedIndex="{Binding SelectedSearchTabIndex, Mode=TwoWay}" >
<phone:Pivot.Title>
<TextBlock Text="My Search Options" />
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding QuickSearchButtons}" DataContext="{StaticResource CriteriaViewModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="{Binding Name}" Grid.Row="0">
</Button>
<TextBlock Text="{Binding Description}" Grid.Row="1">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
</Grid>
As mentioned, this works, and it's not affecting me in anyway as the correct data is always displayed.
I can somehow see what's happening but why on earth would the ItemsSource be set for each of the defined pivot headers. Surely, the only important one is the one coming into visibility!
I don't know if Pivots are suppose to be used the way I'm using them. It seems, from what I've seen so far that normally a view is assigned to each PivotItem. This is not how I want my solution to work!
I just want numerous headers which are used to groups things in a specific manner and whatever is displayed under each is build dynamically but on the same view i.e. list of buttons and label.
Any ideas on how I could get scenario 1) to work and if I'm stuck with scenario 2, how to stop it from being triggered based on the number of pivot header items?
Thanks.
Problem solved!
The QuickSearchTabs was an observable collection of QuickSearchTab when it should have been an observable collection of ViewModel i.e. QuickSearchTabViewModel and within this viewModel, it will load the observable collection of relevant QuickSearchButtons for each of the tab.
Having a QuickSearchTabViewModel provides more flexibility and it will allow access to the current tab (header), and other relevant properties including everything maintain within each of these tabs such as, in my case the buttons.
Hope this helps.