For a WinRT App, I have a GridView where items are grouped so that each group contains a header and his group element.
I want a button in the app bar, to pass all the item in my gridView to the selected state (with the purple border and the checkbox , like when I right click on an item).
I try to add each item to the SelectedItems list of my GridView but it doesn't do anything.
private void FavoriButton_Click_1(object sender, RoutedEventArgs e)
{
foreach (Categorie cat in coll)
itemGridView.SelectedItems.Add(cat);
}
Does anyone know how I can put all my items of a grid view to the selectedState (with the purple border and checkbox) ?
Here is the code
public sealed partial class HomePage : LayoutAwarePage
{
ObservableCollection<Categorie> coll = new ObservableCollection<Categorie>();
public HomePage()
{
this.InitializeComponent();
cvs1.Source = coll;
(itemGridView as ListViewBase).ItemsSource = this.cvs1.View.CollectionGroups;
}
async private void FillPage()
{
var categories = App.api.Categories_Get();
if (categories == null || categories.Count == 0)
return;
for (var i = 0; i < categories.Count; i++)
coll.Insert(i, categories[i]);
}
private void FavoriButton_Click_1(object sender, RoutedEventArgs e)
{
foreach (Categorie cat in coll)
{
itemGridView.SelectedItems.Add(cat);
}
}
et le XAML
<common:LayoutAwarePage
x:Class="NMA.Pages.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NMA"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:common="using:NMA.Common"
mc:Ignorable="d">
<common:LayoutAwarePage.Resources>
<CollectionViewSource x:Name="cvs1" ItemsPath="listArt" IsSourceGrouped="True" />
<DataTemplate x:Key="Standard250x250ItemTemplatePerso">
<Grid HorizontalAlignment="Left" Width="270" Height="210" VariableSizedWrapGrid.ColumnSpan="1" VariableSizedWrapGrid.RowSpan="1" local:Tilt.IsTiltEnabled="False" >
<Image Width="270" Height="210" Source="{Binding ImgArt}" CacheMode="BitmapCache" VerticalAlignment="Top"/>
</Grid>
</DataTemplate>
</common:LayoutAwarePage.Resources>
<Grid Background="Transparent" x:Name="MyGrid">
<Grid x:Name="NormalGrid">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<local:VariableGridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Items"
Grid.RowSpan="2"
Padding="120,130,120,74"
ItemsSource="{Binding Source={StaticResource cvs1}}"
ItemTemplate="{StaticResource Standard250x250ItemTemplatePerso}"
IsSwipeEnabled="False"
IsItemClickEnabled="True"
Background="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollMode="Disabled" SelectionMode="Multiple">
<local:VariableGridView.ItemsPanel >
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" Background="Transparent" local:Tilt.IsTiltEnabled="False" Margin="0,0,100,0" />
</ItemsPanelTemplate>
</local:VariableGridView.ItemsPanel>
<local:VariableGridView.GroupStyle>
<GroupStyle >
<GroupStyle.HeaderTemplate>
<DataTemplate x:Name="MyDataTemplate">
<Button x:Name="HeaderButton" AutomationProperties.Name="MyHeaderButton" Click="HeaderButton_Click_1" Style="{StaticResource ButtonHeader_Style}" Content="{Binding NomCat}" FontSize="26" FontFamily="{StaticResource SegoeWPLight}" Margin="-24,0,0,20" Width="900" Background="Transparent">
</Button>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid ItemWidth="270" ItemHeight="210" Orientation="Vertical" Margin="0,0,-30,0" MaximumRowsOrColumns="4" Background="Transparent" Width="900">
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</local:VariableGridView.GroupStyle>
</local:VariableGridView>
</Grid>
</common:LayoutAwarePage>
Thanks a lot
I actually found it, I was trying hard to go across the visual Tree while it was simple with the ItemContainerGenerator.
private void FavoriButton_Click_1(object sender, RoutedEventArgs e)
{
for( var i = 0 ; i<itemGridView.Items.Count ; i++)
{
(itemGridView.ItemContainerGenerator.ContainerFromIndex(i) as GridViewItem).IsSelected = true;
}
}
Quite easy after all.
Related
In UWP C#, I have one ListView in upper row & another in lower row. When I drag a listitem from upper ListView & drop it on lower ListView, I am getting the source. But, I am unable to get the destination. ie) the listview item/(Folder object in my case) where I dropped.
<ListView Name="ListviewCars"
CanDragItems="True" DragItemsStarting="ListviewCars_DragItemsStarting"
SelectionMode="Single" IsItemClickEnabled="True"
DataContext="Cars" ItemsSource="{Binding CarsCollection}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Background="Transparent" Height="80" Orientation="Horizontal"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate >
<DataTemplate>
<Grid Name="GrdCars" >
<Grid Height="80" Width="90" Padding="5">
<Grid.Background>
<ImageBrush Stretch="Uniform" ImageSource="Assets/car.png"/>
</Grid.Background>
<TextBlock Text="{Binding Name}" FontWeight="Bold" TextWrapping="Wrap" TextAlignment="Center"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Name="GrdViewImg" ScrollViewer.VerticalScrollBarVisibility="Disabled"
AllowDrop="True" DragOver="Image_DragOver"
Drop="Image_OnDrop"
DataContext="Folders" ItemsSource="{Binding FolderCollection}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Background="Transparent" Height="80" Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate >
<DataTemplate>
<Grid Name="GrdForFolderMenu" RightTapped="GrdForFolderMenu_RightTapped">
<Grid Height="80" Width="90" Padding="5">
<Grid.Background>
<ImageBrush Stretch="UniformToFill" ImageSource="Assets/Folderimage.png"/>
</Grid.Background>
<TextBlock Text="{Binding Name}" FontWeight="Bold" TextWrapping="Wrap" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have found a simple solution myself. I get the source from DragItemsStarting event of the SoureListView. and target item (as mentioned by ashchuk) from a Grid placed inside Datatemplate of Target ListView. as shown below. Everything works fine now!
(Cars is my Source custom list item. Folders is my Target custom list item)
private void SoureListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
Cars x = e.Items[0] as Cars;
string DraggedSourceCar = x.Name;
e.Data.Properties.Add("myArgs", DraggedSourceCar);
}
private void GridInsideDatatemplateOfTargetListview_Drop(object sender, DragEventArgs e)
{
var x = sender as Grid;
var y = x.DataContext as Folders;
string toMoveFolderName = y.Name;
string DraggedSourceCar = e.DataView.Properties["myArgs"].ToString();
Debug.WriteLine(DraggedSourceCar + Environment.NewLine + toMoveFolderName );
}
private void TargetListview_DragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Copy;
}
You have to find out by yourself = DragEventArgs.GetPosition() in the destination drop, then the underlying item with smoe helper functions
public static object GetObjectAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
// ItemContainer - can be ListViewItem, or TreeViewItem and so on(depends on control)
ItemContainer obj = GetContainerAtPoint<ItemContainer>(control, p);
if (obj == null)
return null;
return control.ItemContainerGenerator.ItemFromContainer(obj);
}
public static ItemContainer GetContainerAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
HitTestResult result = VisualTreeHelper.HitTest(control, p);
if (result != null)
{
DependencyObject obj = result.VisualHit;
while (VisualTreeHelper.GetParent(obj) != null && !(obj is ItemContainer))
{
obj = VisualTreeHelper.GetParent(obj);
}
// Will return null if not found
return obj as ItemContainer;
}
else return null;
}
Did you checked this sample?
After some research I found what DragEventArgs contains an OriginalSource property with Name matches the name of target list when Drop event invoked.
I'm not checked it with folders and subfolders, but maybe OriginalSource will contain folder where item dropped.
<TextBlock Grid.Row="1" Margin="8,4"
VerticalAlignment="Bottom"
Text="All Items"/>
<ListView x:Name="SourceListView"
Grid.Row="2" Margin="8,4"
SelectionMode="Extended"
CanDragItems="True"
DragItemsStarting="SourceListView_DragItemsStarting"/>
<TextBlock Grid.Row="1" Grid.Column="1" Margin="8,4"
VerticalAlignment="Bottom"
Text="Selection"/>
<ListView x:Name="TargetListView"
Grid.Row="2" Grid.Column="1" Margin="8,4"
AllowDrop="True" CanReorderItems="True" CanDragItems="True"
DragOver="TargetListView_DragOver"
Drop="TargetListView_Drop"
DragItemsStarting="TargetListView_DragItemsStarting"
DragItemsCompleted="TargetListView_DragItemsCompleted"/>
And here is printscreen with fired breakpoint:
EDIT:
To get an item inside of TargetList you can do a trick.
I think you use DataTemplate to display custom list items ("folders"). You can see a sample below. As you see I add Grid_DragOver trigger.
<Page.Resources>
<DataTemplate x:Key="ListViewDataTemplate">
<Grid Margin="20,5" DragOver="Grid_DragOver"
BorderBrush="White" BorderThickness="5" AllowDrop="True">
<TextBlock Margin="10" LineHeight="40" FontSize="32" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Page.Resources>
This way Grid_DragOver will be invoked when mouse pointer enter inside the Grid in DataTemplate.
And if you use binding List<YourFolderClass> as data source, you'll get folder in DataContext. For example I used this:
var SampleData = new ObservableCollection<string>
{
"My Research Paper",
"Electricity Bill",
"My To-do list",
"TV sales receipt",
"Water Bill",
"Grocery List",
"Superbowl schedule",
"World Cup E-ticket"
};
You can see all code in gist.
I have a window that I'm basically building ghetto minesweeper in. I have a grid that I feed a jagged array into, set up so that it will adapt to any change in the size of the array (no hard set values or rows/columns). Over top of that, I have a grid of blank buttons that simply adapts in size to the grid below.
When you click a button, it hides revealing the value under it, and I need some way to return the position of the button clicked, so I can compare against the original jagged array to find out whether not the item was a bomb. (this would also help me for doing a fill action on empty tiles). But given how I have it set up, the Grid.GetRow or Grid.GetColumn just return 0's.
Does anyone know how I can get the array position (preferably row and column) from the setup that I have?
XAML Below, the C# click events follow it.
<Window x:Class="MinesweeperWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Minesweeper" SizeToContent="WidthAndHeight" Height="Auto" Width="Auto">
<Window.Resources>
<DataTemplate x:Key="Buttons_Template">
<Button Content=""
Height="20"
Width="20"
Margin="0,0,0,0"
Visibility="Visible"
Click="ButtonClick"
MouseRightButtonUp="RightClick"/>
</DataTemplate>
<DataTemplate x:Key="DataTemplate_2">
<TextBlock Text="{Binding}"
Height="20"
Width="20"
Margin="0,0,0,0"
FontFamily="Rockwell"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Padding="5"/>
</DataTemplate>
<DataTemplate x:Key="DataTemplate_1">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_2}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="Buttons_Template2">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource Buttons_Template}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<TextBlock x:Name="RemainingMines" HorizontalAlignment="Left" />
<TextBlock x:Name="Difficulty" HorizontalAlignment="Center" />
<TextBlock x:Name="Timer" HorizontalAlignment="Right" />
</Grid>
<Grid Name="ResetButton" Grid.Row="1">
<Button Name="Reset" Content="Reset"/>
</Grid>
<Grid Name="GridBoard" ShowGridLines="True" Grid.Row="2">
<ItemsControl x:Name="GridItems" ItemTemplate="{DynamicResource DataTemplate_1}"/>
</Grid>
<Grid Name="ButtonsBoard" ShowGridLines="True" Grid.Row="2">
<ItemsControl x:Name="ButtonItems" ItemTemplate="{DynamicResource Buttons_Template2}"/>
</Grid>
</Grid>
</Window>
Click Methods in C#
private void ButtonClick(object sender, RoutedEventArgs e)
{
int col = Grid.GetColumn((Button)sender); //this just returns 0
int row = Grid.GetRow((Button)sender); //this just returns 0
Button source = e.Source as Button;
source.Visibility = Visibility.Hidden;
Console.WriteLine("L: {0} x {1}", col, row); //prints L: 0 x 0
}
private void RightClick(object sender, RoutedEventArgs e)
{
int col = Grid.GetColumn((Button)sender); //this just returns 0
int row = Grid.GetRow((Button)sender); //this just returns 0
Button source = e.Source as Button;
if(source.Content.Equals(""))
{
source.Content = "\u2691";
}
else
{
source.Content = "";
}
Console.WriteLine("R: {0} x {1}", col, row); //prints R: 0 x 0
}
Any help would be appreciated on this.
You need to use appropriate control for buttons to host. In your xaml you are using items control inside Grid. But Items control do not have row and column index. Thats why you are not able to get the index.
Use UniformGrid or some relevant control.
You can refer this article
https://stackoverflow.com/a/13588066/5273015
Will help you a lot in other assignments as well
I want to create a gallery image on the first page contains a thumbnail for that category and when thumbnail is selected, it will open the image and description of the selected image in flipview (can be swipe to the right and to the left when thumbnail is selected for the image before and after). I have difficulties when applying it into flipview.
Code:
MainPage XAML
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="3"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick" Background="#FF6996D1" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="240" Height="180">
<Border>
<Image Source="{Binding ImagePath}" Stretch="Uniform" AutomationProperties.Name="{Binding Title}"/>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
MainPage:
public MainPage()
{
this.InitializeComponent();
Gallery();
}
private async void Gallery()
{
var sampleDataGroups = await DataItemSource.GetGroupsAsync();
this.DefaultViewModel["Groups"] = sampleDataGroups;
}
void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
// Navigate to the appropriate destination page, configuring the new page
// by passing required information as a navigation parameter
var itemId = ((SampleDataItem)e.ClickedItem).UniqueId;
this.Frame.Navigate(typeof(ItemDetailPage), itemId);
}
ItemDetailPage XAML:
<Grid Grid.Row="1" x:Name="contentRegion" Background="#FF6996D1">
<Image Source="{Binding ImagePath}" HorizontalAlignment="Left" Height="559" Margin="84,20,0,49" VerticalAlignment="Center" Width="732"/>
<ScrollViewer x:Name="myScroll" VerticalScrollBarVisibility="Auto" Margin="852,60,50,91" VerticalScrollMode="Auto" HorizontalScrollBarVisibility="Auto">
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" Height="2210" Width="425" FontSize="27" TextAlignment="Justify" />
</ScrollViewer>
</Grid>
ItemDetailPage Code:
public ItemDetailPage()
{
this.InitializeComponent();
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += navigationHelper_LoadState;
}
private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var item = await DataItemSource.GetItemAsync((String)e.NavigationParameter);
this.DefaultViewModel["Item"] = item;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
navigationHelper.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
navigationHelper.OnNavigatedFrom(e);
}
How do I apply flipview on ItemDetailPage?
Note:
For more code detail you can view the sample
To apply flipview on ItemDetailPage, we can add FlipView under "contentRegion" and set the Image and ScrollViewer as FlipView's ItemTemplate like following:
<Grid x:Name="contentRegion" Grid.Row="1" Background="#FF6996D1">
<FlipView ItemsSource="{Binding Group.Items}" SelectedItem="{Binding Item, Mode=TwoWay}">
<FlipView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Width="732"
Height="559"
Margin="84,20,0,49"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Source="{Binding ImagePath}" />
<ScrollViewer x:Name="myScroll"
Margin="852,60,50,91"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Auto">
<TextBlock Width="425"
Height="2210"
FontSize="27"
Text="{Binding Description}"
TextAlignment="Justify"
TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Grid>
And in code-behind, set the data source like following:
private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var item = await DataItemSource.GetItemAsync((String)e.NavigationParameter);
var group = await DataItemSource.GetGroupByItemAsync(item);
this.DefaultViewModel["Group"] = group;
this.DefaultViewModel["Item"] = item;
}
Here I add a GetGroupByItemAsync(SampleDataItem item) method in DataItemSource which can retrieve the group according to the item.
public static async Task<SampleDataGroup> GetGroupByItemAsync(SampleDataItem item)
{
await _DataItemSource.GetSampleDataAsync();
// Simple linear search is acceptable for small data sets
var matches = _DataItemSource.Groups.Where(group => group.Items.Contains(item));
if (matches.Count() == 1) return matches.First();
return null;
}
Besides these, we also need to remove DataContext="{Binding Item}" form root Grid and put in in <Grid Background="#FF6996D1" DataContext="{Binding Item}">.
After this, the FlipView should be able to work. However here is a strange behavior, if we select the second or third image, the previous image in flip view won't show like following
We are investigating on this issue. As a workaround, we can disable FlipView's virtualization by changing its ItemsPanel like:
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
The complete XAML code of ItemDetailPage might like:
<Page x:Class="ImageGalerry.ItemDetailPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:ImageGalerry.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="using:ImageGalerry.Data"
xmlns:local="using:ImageGalerry"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding DefaultViewModel,
RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Grid d:DataContext="{Binding Groups[0].Items[0], Source={d:DesignData Source=/DataModel/DataItem.json, Type=data:DataItemSource}}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid Background="#FF6996D1" DataContext="{Binding Item}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1366" />
</Grid.ColumnDefinitions>
<Button x:Name="backButton"
Margin="39,59,0,0"
VerticalAlignment="Top"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
AutomationProperties.Name="Back"
Command="{Binding NavigationHelper.GoBackCommand,
ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}" />
<TextBlock x:Name="pageTitle"
Margin="120,40,30,40"
VerticalAlignment="Top"
IsHitTestVisible="false"
Style="{StaticResource HeaderTextBlockStyle}"
Text="{Binding Title}"
TextWrapping="NoWrap" />
<!--<MediaElement x:Name="mediaplayer" Source="images/ost.mp3" AudioCategory="BackgroundCapableMedia" />
<Button x:Name="PlayButton" Content="Stop" Click="PlayButton_Click" Margin="1274,72,0,30" />-->
</Grid>
<Grid x:Name="contentRegion" Grid.Row="1" Background="#FF6996D1">
<FlipView ItemsSource="{Binding Group.Items}" SelectedItem="{Binding Item, Mode=TwoWay}">
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
<FlipView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Width="732"
Height="559"
Margin="84,20,0,49"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Source="{Binding ImagePath}" />
<ScrollViewer x:Name="myScroll"
Margin="852,60,50,91"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Auto">
<TextBlock Width="425"
Height="2210"
FontSize="27"
Text="{Binding Description}"
TextAlignment="Justify"
TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Grid>
</Grid>
</Page>
Please note that disabling UI virtualization for FlipView may negatively impact performance especially when there are a lot of images. If you have a lot of images, you can try to use incremental loading and data virtualization.
I know there are a lot of question like this in the web, but believe me I spent on this a lot of hours and I still not success, I really will glad for any help!
I loading various images in run time and I want to show them in list box (small images, then the user should click on one of them and show him in real size).
my code is:
public partial class MainWindow : Window
{
int imageNumber = 0;
public List<String> ImagePath = new List<String>();
public MainWindow()
{
InitializeComponent();
lb_Images.ItemsSource = ImagePath;
}
private void bu_addImage_Click(object sender, RoutedEventArgs e)
{
addImageToListBox();
}
private void addImageToListBox()
{
imageNumber++;
if (imageNumber == 4) imageNumber = 0;
string directoryPath = AppDomain.CurrentDomain.BaseDirectory;
// load input image
string ImageFilename = directoryPath + "img";
ImageFilename += imageNumber.ToString();
ImageFilename += ".jpg";
ImagePath.Add(ImageFilename);
}
}
and the xaml is:
<Window x:Class="forQuestionWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="216" Width="519">
<Window.Resources>
<DataTemplate x:Key="ImageGalleryDataTemplate">
<Grid>
<Border BorderBrush="#FFFF9800" BorderThickness="1" Width="120" Height="120" Padding="5" Margin="5" CornerRadius="6">
<!--Bind Image Path in Image Control-->
<Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Center">
<!--View Large Image on Image Control Tooltip-->
<Image.ToolTip>
<Grid>
<Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Center" Height="200" Width="200"></Image>
</Grid>
</Image.ToolTip>
</Image>
</Border>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
<!--Display Images on UniformGrid Panel-->
<UniformGrid Rows="1" Columns="25" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Canvas Height="177" HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top" Width="497">
<ListBox Canvas.Left="6" Canvas.Top="5" Height="166" Name="lb_Images" Width="441"
BorderBrush="{x:Null}" DataContext="{Binding Source={StaticResource ImageGalleryDataTemplate}}"
ItemsSource="{Binding Source={StaticResource ImageGalleryItemsPanelTemplate}}">
</ListBox>
<Button Canvas.Left="453" Canvas.Top="26" Content="Add" Height="64" Name="bu_addImage" Width="38" Click="bu_addImage_Click" />
</Canvas>
</Grid>
</Window>
I know that the list box updated when I add image path to the list because if I debug I found some items under lb_Images.items, but I show nothing.
I'll glad for any help! thank you!!
Some notes
DataContext for ListBox it's not necessary, then you set ItemSource. Instead of set the ItemTemplate
In DataTemplate remove the {Binding ImagePath}, instead of write {Binding}, because in this case the elements of the DataTemplate inherit DataContext.
When you add new items to ListBox.Items, you must call ListBox.Items.Refresh() or use the ObservableCollection<T>, because:
ObservableCollection represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
Try this example:
XAML
<Window.Resources>
<DataTemplate x:Key="ImageGalleryDataTemplate">
<Grid>
<Border BorderBrush="#FFFF9800" BorderThickness="1" Width="120" Height="120" Padding="5" Margin="5" CornerRadius="6">
<Image Source="{Binding}" Stretch="Fill" HorizontalAlignment="Center">
<Image.ToolTip>
<Grid>
<Image Source="{Binding}" Stretch="Fill" HorizontalAlignment="Center" Height="200" Width="200" />
</Grid>
</Image.ToolTip>
</Image>
</Border>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
<UniformGrid Rows="1" Columns="25" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Canvas Height="177" HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top" Width="497">
<ListBox Canvas.Left="6" Canvas.Top="5" Height="166" Name="lb_Images" Width="441"
ItemTemplate="{StaticResource ImageGalleryDataTemplate}"
ItemsSource="{Binding Path=ImagePath}">
</ListBox>
<Button Canvas.Left="453" Canvas.Top="26" Content="Add" Height="64" Name="bu_addImage" Width="38" Click="bu_addImage_Click" />
</Canvas>
</Grid>
Code-behind
public partial class MainWindow : Window
{
int imageNumber = 0;
public List<String> ImagePath = new List<String>();
public MainWindow()
{
InitializeComponent();
lb_Images.ItemsSource = ImagePath;
}
private void bu_addImage_Click(object sender, RoutedEventArgs e)
{
addImageToListBox();
}
private void addImageToListBox()
{
imageNumber++;
if (imageNumber == 4) imageNumber = 0;
string directoryPath = AppDomain.CurrentDomain.BaseDirectory;
// load input image
string ImageFilename = directoryPath + "img";
ImageFilename += imageNumber.ToString();
ImageFilename += ".jpg";
ImagePath.Add(ImageFilename);
lb_Images.Items.Refresh();
}
}
The standard GridApp template is as follows:
Variable Sized Grouped GridView template is as follows:
How to make a template for your application, so that it looks like this:
For example, this design in all applications Bing for windows 8:
Code for Variable Sized Grouped GridView template:
<UserControl.Resources>
<!-- Collection of grouped items displayed by this page -->
<CollectionViewSource
x:Name="groupedItemsViewSource"
Source="{Binding Groups}"
IsSourceGrouped="true"
ItemsPath="Items"
d:Source="{Binding ItemGroups, Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}"/>
<DataTemplate x:Key="CustomTileItem">
<Grid >
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel VerticalAlignment="Bottom" >
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</UserControl.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Grid.Column="1" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<!-- Horizontal scrolling grid used in most view states -->
<ScrollViewer
x:Name="itemGridScrollViewer"
AutomationProperties.AutomationId="ItemGridScrollViewer"
Grid.Row="1"
Margin="0,-3,0,0"
Style="{StaticResource HorizontalScrollViewerStyle}">
<local:MyGridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Margin="116,0,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource CustomTileItem}"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<local:MyGridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</local:MyGridView.ItemsPanel>
<local:MyGridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,0,6">
<Button
AutomationProperties.Name="Group Title"
Content="{Binding Title}"
Click="Header_Click"
Style="{StaticResource TextButtonStyle}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid ItemWidth="75" ItemHeight="150" Orientation="Vertical" Margin="0,0,80,0" MaximumRowsOrColumns="3"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</local:MyGridView.GroupStyle>
</local:MyGridView>
</ScrollViewer>
and:
public class MyGridView : GridView
{
private int rowVal;
private int colVal;
private Random _rand;
private List<Size> _sequence;
public MyGridView()
{
_rand = new Random();
_sequence = new List<Size> {
LayoutSizes.PrimaryItem,
LayoutSizes.SecondarySmallItem, LayoutSizes.SecondarySmallItem,
LayoutSizes.SecondarySmallItem,
LayoutSizes.SecondaryTallItem,
LayoutSizes.OtherSmallItem, LayoutSizes.OtherSmallItem, LayoutSizes.OtherSmallItem
};
}
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
SampleDataItem dataItem = item as SampleDataItem;
int index = -1;
if (dataItem != null)
{
index = dataItem.Group.Items.IndexOf(dataItem);
}
if (index >= 0 && index < _sequence.Count)
{
colVal = (int)_sequence[index].Width;
rowVal = (int)_sequence[index].Height;
}
else
{
colVal = (int)LayoutSizes.OtherSmallItem.Width;
rowVal = (int)LayoutSizes.OtherSmallItem.Height;
}
VariableSizedWrapGrid.SetRowSpan(element as UIElement, rowVal);
VariableSizedWrapGrid.SetColumnSpan(element as UIElement, colVal);
}
}
public static class LayoutSizes
{
public static Size PrimaryItem = new Size(6, 2);
public static Size SecondarySmallItem = new Size(3, 1);
public static Size SecondaryTallItem = new Size(3, 2);
public static Size OtherSmallItem = new Size(2, 1);
}
For example with "Variable Sized Grouped GridView template", we can combine the rows or columns, and how to set the first element height = "auto", and all other elements that have different widths and heights, but grouped as "Variable Sized Grouped GridView template"?
View this post:
http://blogs.msdn.com/b/synergist/archive/2012/09/25/windows-store-app-xaml-gridview-with-variable-templates.aspx
I think this is what you need.