I have a Panorama control where i need to programmaticaly add items which are images.
I want to implement them so that flicking on the image slide to second image and so on..
I did add images to the panaroma item but it always shows one image only.
for (int i = 0; i < 10; i++)
{
image_new = new Image();
PanoramaItem pi = new PanoramaItem();
image_new.Source = "Some image Bitmap";
pi.Content = image_new;
image_panaroma.Items.Add(pi);
}
xaml layout is :
<Grid x:Name="LayoutRoot">
<controls:Panorama Name="image_panaroma">
</controls:Panorama>
</Grid>
Can someone tell me what is wrong?
Also is there any other way possible to give sliding transition to images?
You don't say what exception you get, but I think a better approach would be to create an ItemTemplate for the Panorama control and bind it to your list of objects.
public class ItemData
{
public string Name { get; set; }
public string Path { get; set; }
}
...
List<ItemData> items = new List<ItemData>(10);
for (int i = 0; i < 10; i++)
{
items.Add(new ItemData { Name = "Something", Path = "Image path" });
}
this.image_panorama.ItemsSource = items;
Your XAML would look something like this:
<controls:Panorama x:Name="image_panorama">
<controls:Panorama.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</controls:Panorama.HeaderTemplate>
<controls:Panorama.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Path}" />
</DataTemplate>
</controls:Panorama.ItemTemplate>
</controls:Panorama>
You say that this only shows 1 image. Is this the same image 10 times (one for each pivotItem) or is only 1 pivotItem being created?
If it's the first then it could be how you're creating the image and/or setting the source.
Your example code doesn't show that you're using a different image source or how image_new is scoped. Without a more complete example of your actual code it's hard to say for sure.
The following will (works-on-my-machine) create 10 items all with the same image:
public MainPage()
{
InitializeComponent();
this.Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
for (var i = 0; i < 10; i++)
{
var image_new = new Image();
var pi = new PanoramaItem();
var bi = new BitmapImage(new Uri("/Background.png", UriKind.Relative));
image_new.Source = bi;
pi.Content = image_new;
image_panaroma.Items.Add(pi);
}
}
Are you using the January Update? (I am-see above for WOMM disclaimer) This update includes changes that affect the panorama control.
Related
Looking forward to your assistance once again :)
I'm trying to have the buttons on the far right be able to delete their row in the tableview control. Right now they now about which row they are on but I cannot connect this information to the parent. The table view is populated with a custom viewcell.
The custom view cell contains two different pickers, two entry fields and a button. I haven't found a cleaner way to execute this as I have the picker's data which isn't related to the # of rows in the data table control.
Currently when you click a button on the right it posts to the console what row was selected but I don't know of a way to connect that to its parent in order to actually delete that row on the data table
View Cell Code Behind
public partial class RecipeIngredientViewCell : ViewCell
{
ObservableCollection<clIngredient> _listIngredients = new ObservableCollection<clIngredient>();
public ObservableCollection<clIngredient> listIngredients { get { return _listIngredients; } }
ObservableCollection<clUnit> _listUnit = new ObservableCollection<clUnit>();
public ObservableCollection<clUnit> funclistUnit { get { return _listUnit; } }
clRecipeIngredient _recipeIngredient;
int _row;
public RecipeIngredientViewCell(clRecipeIngredient passedrecipeIngredient, ObservableCollection<clIngredient> passedlistIngredients, ObservableCollection<clUnit> passedlistUnits, int row)
{
InitializeComponent();
_listIngredients = passedlistIngredients;
_listUnit = passedlistUnits;
_recipeIngredient = passedrecipeIngredient;
_row = row;
this.BindingContext = _recipeIngredient;
//INGREDIENT PICKER
pickerIngredient.ItemsSource = _listIngredients;
for(int x = 0; x < _listIngredients.Count; x++)
{
if (_listIngredients[x].IngredientName == _recipeIngredient.IngredientName)
{
pickerIngredient.SelectedIndex = x;
}
}
//UNIT PICKER
pickerUnit.ItemsSource = _listUnit;
for (int x = 0; x < _listUnit.Count; x++)
{
if (_listUnit[x].UnitName == _recipeIngredient.UnitName)
{
pickerUnit.SelectedIndex = x;
}
}
}
private void btnDeleteRecipeIngredient_Clicked(object sender, EventArgs e)
{
//NOT IMPLEMENTED YET!
Console.WriteLine(_recipeIngredient.IngredientName + " AT ROW " + _row.ToString());
}
private void txtQuantity_TextChanged(object sender, TextChangedEventArgs e)
{
_recipeIngredient.Quantity = txtQuantity.Text.ToDouble();
}
private void txtComment_TextChanged(object sender, TextChangedEventArgs e)
{
_recipeIngredient.Comments = txtComment.Text;
}
private void pickerIngredient_SelectedIndexChanged(object sender, EventArgs e)
{
_recipeIngredient.IngredientName = pickerIngredient.SelectedItem.ToString();
}
private void pickerUnit_SelectedIndexChanged(object sender, EventArgs e)
{
_recipeIngredient.UnitName = pickerIngredient.SelectedItem.ToString();
}
}
View Cell XAML
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="RecipeDatabaseXamarin.Views.RecipeIngredientViewCell">
<Grid VerticalOptions="CenterAndExpand" Padding = "20, 0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<Picker Grid.Column = "0" x:Name="pickerIngredient" HorizontalOptions = "StartAndExpand" SelectedIndexChanged="pickerIngredient_SelectedIndexChanged"/>
<Entry Grid.Column = "1" x:Name ="txtQuantity" HorizontalOptions = "StartAndExpand" Text = "{Binding Quantity}" TextChanged="txtQuantity_TextChanged" />
<Picker Grid.Column = "2" x:Name ="pickerUnit" HorizontalOptions = "StartAndExpand" SelectedIndexChanged="pickerUnit_SelectedIndexChanged"/>
<Entry Grid.Column = "3" x:Name="txtComment" HorizontalOptions = "StartAndExpand" Text = "{Binding Comments}" TextChanged="txtComment_TextChanged" WidthRequest="150"/>
<Button Grid.Column = "4" x:Name="btnDeleteRecipeIngredient" HorizontalOptions = "StartAndExpand" Text = "Delete Ingredient" Clicked="btnDeleteRecipeIngredient_Clicked"/>
</Grid>
Code Behind for Page
var section = new TableSection();
for(int i = 0;i<_downloadedRecipeIngredients.Count;i++)
{
var cell = new RecipeIngredientViewCell(downloadedRecipeIngredients[i], listIngredients, listUnit, i);
section.Add(cell);
}
tblData.Root.Add(section);
In the main page code behind I want the button to run a block of code to execute something such as
tblData.Root.del(ROW_INDEX);
Thanks!
I believe I have this solved. Will post the solution when I get back from the 4th weekend.
The solution to this problem is answered on another post. Basically the solution is easier once MVVM is implemented even though it was a pain to get it to work on the picker withing the listView control.
This other thread has sample code which you can run.
Trying to set picker within listview MVVM Xamarin
If anyone runs into the same issue please post and I'll try to respond back as this issue was a PAIN!!!!
I am not a notorious xamarin programmer, but you have your width to auto, which most likely changes the whole grid the moment the width changes. Therefore it will align the buttons differently too.
It seems you could position the horizontalOptions to "End" to at least put the buttons to the end of the screen. If you want to have it always the same, I would give them a certain width per section.
I'm trying to use a ListBox to choose an entry and then display a picture belonging to this selected entry. But just at the beginning I got my first problem: filling the ListBox with binding is working, but if I click on one line in my running program, it doesn't select the line. I can just see the highlighted hover effect, but not select a line. Any ideas what my mistake could be?
This is my XAML:
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontSize="24"/>
And in MainWindow.xaml.cs I'm filling the ListBox with entries:
private void fillEntrySelectionListBox()
{
//Fill listBox with entries for active user
DataContext = this;
entryItems = new ObservableCollection<ComboBoxItem>();
foreach (HistoryEntry h in activeUser.History)
{
var cbItem = new ComboBoxItem();
cbItem.Content = h.toString();
entryItems.Add(cbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + activeUser.Id;
//show image matching the selected entry
if (activeUser.History != null)
{
int index = entrySelection.SelectedIndex;
if (index != -1 && index < activeUser.History.Count)
{
this.entryImage.Source = activeUser.History[index].Image;
}
}
}
So I can see my ListBox correctly filled, but not select anything - so I can't go on with loading the picture matching the selected entry.
I'm still quite new to programming, so any help would be great :)
EDIT: If someone takes a look at this thread later: here's the - quite obvious -solution
XAML now looks like this
<ListBox x:Name="entrySelection" ItemsSource="{Binding Path=entryItems}" HorizontalAlignment="Left" Height="335" Margin="428,349,0,0" VerticalAlignment="Top" Width="540" FontFamily="Siemens sans" FontSize="24">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code behind to fill it:
//Fill listbox with entries for selected user
DataContext = this;
entryItems = new ObservableCollection<DataItem>();
foreach (HistoryEntry h in selectedUser.History)
{
var lbItem = new DataItem(h.toString());
entryItems.Add(lbItem);
}
this.entrySelection.ItemsSource = entryItems;
labelEntrySelection.Text = "Einträge für: " + selectedUser.Id;
And new Class DataItem:
class DataItem
{
private String text;
public DataItem(String s)
{
text = s;
}
public String Text
{
get
{
return text;
}
}
}
You are filling it with ComboBoxItem, which is not relevant to the ListBox, and also wrong by definition.
You need to have the ObservableCollection filled with data items.
Meaning, make a class that contains the data you want to store, and the ListBox will generate a ListBoxItem automatically per data item.
http://www.wpf-tutorial.com/list-controls/listbox-control/
So I am able to display images from my custom folder in the Pictures Library to my ListView in the app. However, when that custom folder has 3 or more images, it's either Out of Memory Exception occurs or the app just crashes and Visual Studio doesn't even realize that the app have crashed. My question is how can I make this work?
Here are my codes...
In the xaml.cs file:
List<StorageFile> FileList = (await temp.GetFilesAsync()).ToList();
List<ImageItem> ImageList = new List<ImageItem>();
for (int i = 0; i < FileList.Count; i++)
{
using (IRandomAccessStream FileStream = await FileList[i].OpenAsync(FileAccessMode.Read))
{
using(StorageItemThumbnail thumbnail = await file.GetThumbnailAsync(ThumbnailMode.PicturesView))
{
if (thumbnail != null && thumbnail.Type == ThumbnailType.Image)
{
BitmapImage bitmap = new BitmapImage();
await bitmap.SetSourceAsync(FileStream);
ImageList.Add(new ImageItem() { ImageData = bitmap });
}
}
}
}
this.PhotoListView.DataContext = ImageList;
Here is my Helper Class:
public class ImageItem
{
public BitmapImage ImageData { get; set; }
}
Here is my xaml ListView code:
<ListView Grid.Column="1"
Grid.Row="0"
x:Name="PhotoListView"
Grid.RowSpan="1"
ItemsSource="{Binding}">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageData}"
Margin="10"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
The problem with your code is that when you use BitmapImage you didn't specify the DecodePixelHeight and DecodePixelWidth, you can solve the issue in 2 ways:
the first is to specify the DecodePixelHeight and DecodePixelWidth, the second is to pass the path of the image to the list view using this code:
List<StorageFile> FileList = (await temp.GetFilesAsync()).ToList();
List<string> ImageList = new List<string>();
foreach(var file in FileList)
{
ImageList.Add(file.Path);
}
this.PhotoListView.DataContext = ImageList;
the Image control is able to do all the stuff for you, and takes care of the memory management as well.
I think your main problem is settings the ItemsPanelTemplate to Stackpanel. This kills virtualization. There is no reason for you to override the default item panel.
Also as frenk91 mentions, adding DecodePixelHeight and DecodePixelWidth to your XAML may be useful.
I am trying to update the list which is Bound to ListBox , When the scroll bar reaches end.I need to update the list and show the changes in UI also.Here it is not updating automatically.Can someone please help me in fulfilling my requirement.
If i tried to use TwoWay mode, It shows below error:
Error : Invalid binding path 'itemsList' : Cannot bind type 'System.Collections.Generic.List(System.String)' to 'System.Object' without a converter
<ScrollViewer
x:Name="sv"
ViewChanged="OnScrollViewerViewChanged">
<ListBox x:Name="listView"
HorizontalAlignment="Left"
Height="Auto"
VerticalAlignment="Top"
Width="172"
ItemsSource="{x:Bind itemsList, Mode=OneWay}"/>
</ScrollViewer>
and the code
public List<String> itemsList = new List<string>();
private void OnScrollViewerViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var verticalOffset = sv.VerticalOffset;
var maxVerticalOffset = sv.ScrollableHeight; //sv.ExtentHeight - sv.ViewportHeight;
if (maxVerticalOffset < 0 ||
verticalOffset == maxVerticalOffset)
{
// Scrolled to bottom
Util.debugLog("REACHED BOTTOM");
int i;
// itemsList = null;
itemsList.Clear();
for (i = 0; i < 20; i++)
{
itemsList.Add("Item number " + i + 900);
}
}
else
{
// Not scrolled to bottom
// rect.Fill = new SolidColorBrush(Colors.Yellow);
}
}
Here(In below link) is the answer for my question.Thanks alot for all who tried to answer my question.
https://social.technet.microsoft.com/Forums/en-US/7c730558-f933-4483-8d5b-1710d19f99de/xbind-in-windows-10-mode-one-way-i-am-trying-to-update-the-bind-list-when-scrollview-reached-to?forum=wpf
I want a listbox that will show all the images and text "layers" that I have on my Canvas in silverlight. The code I have currently crashes when I try to view the listbox or when I'm viewing the listbox when I add an element. I can't figure out why. Can someone point me in the right direction with this?
XML -
<Grid DataContext="{Binding Path=Project}">
...
...
<TextBlock Name="textBlock1" Text="Layers" Margin="18,16,0,0" />
<StackPanel Grid.Row="1" Grid.RowSpan="2" Grid.ColumnSpan="2">
<ListBox ItemsSource="{Binding Path=Elements}" Height="175" Name="listBox1" Width="172"/>
</StackPanel>
</Grid>
Project.cs
//List of elements
private ObservableCollection<FrameworkElement> elements;
public ObservableCollection<FrameworkElement> Elements
{
get { return elements; }
set
{
elements = value;
NotifyPropertyChanged("Elements");
}
}
// An example of how an element is added to the Elements collection
// There are also image elements added similarly
private void AddTextElement(object param)
{
TextBlock textBlock = new TextBlock();
textBlock.Text = "New Text";
textBlock.Foreground = new SolidColorBrush(Colors.Gray);
textBlock.FontSize = 25;
textBlock.FontFamily = new FontFamily("Arial");
textBlock.Cursor = Cursors.Hand;
textBlock.Tag = null;
this.Elements.Add(textBlock);
numberOfElements++;
this.SelectedElement = textBlock;
this.selectedTextElement = textBlock;
}
private void AddImageElement(object param)
{
bool? gotImage;
string fileName;
BitmapImage imageSource = GetImageFromLocalMachine(out gotImage, out fileName);
if (gotImage == true)
{
Image image = new Image();
OrderElements(image);
image.Name = fileName;
image.Source = imageSource;
image.Height = imageSource.PixelHeight;
image.Width = imageSource.PixelWidth;
image.MaxHeight = imageSource.PixelHeight;
image.MaxWidth = imageSource.PixelWidth;
image.Cursor = Cursors.Hand;
image.Tag = null;
AddDraggingBehavior(image);
image.MouseLeftButtonUp += element_MouseLeftButtonUp;
this.Elements.Add(image);
numberOfElements++;
this.SelectedElement = image;
this.SelectedImageElement = image;
}
}
One reason might be, because you bind using Path property in your Grid element.
You should use binding source, and set your Project object as a staticresource which you can point to when you call binding source.
Like this:
<Window
xlmns:local="NamespaceOfMyProject">
<Window.Resources>
<local:Project x:key="MyProjectResource" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource MyProjectResource}}>
....
</Grid>
....
</Window>
Reason is: You use "Source" when you point to objects, and "Path" when you point to properties.
Another way to set the DataContext is to do it in the codebehind, using this C# code. But first give your grid a name, so it can be referenced in the codebehind:
<Grid x:Name="myGrid">
Codebehind:
myGrid.DataContext = new Project();
Working with Images incorrectly will typically cause the crash; Show the code for implementation of your Elements and how you setting the images.
Also your XAML is missing ItemTemplate,where u would set the image and text.
I'd guess it's crashing because you've got FrameworkElements that you've added to a Canvas, but then you're also adding them to your List. FrameworkElements generally don't like being added to the visual tree multiple times.
If this is the problem, something like this might work around it (bind your list to ElementsAsStrings):
private ObservableCollection<FrameworkElement> elements;
public ObservableCollection<FrameworkElement> Elements
{
get { return elements; }
set
{
if(elements != null)
elements.CollectionChanged -= onElementsChanged;
elements = value;
if(elements != null)
elements.CollectionChanged += onElementsChanged;
NotifyPropertyChanged("Elements");
NotifyPropertyChanged("ElementsAsStrings");
}
}
public IEnumerable<string> ElementsAsStrings
{
get
{
foreach(var element in Elements)
{
if(element is TextBox)
yield return (element as TextBox).Text;
// More cases here
}
}
}
private void onElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
NotifyPropertyChanged("ElementsAsStrings");
}