Why selected item in ListBox throws error in expression blend? - expression-blend

I am learning expression blend using the following link http://visitmix.com/labs/rosetta/EyesOfBlend/DataTemplates/
It is a very good step by step instruction on using expression blend. I was able to do all the steps successfully and I was able to run the program and got the final result.
Right after step (9), before running the project, when I checked the designer, the designer did not show the image in the big image control I have added in step (9). I knew why, since the selected index of the ListBox was -1, so I changed the selectedindex to 0, now I was able to see the image. But when I compiled the code I get the following error
"Specified argument was out of the range of valid values. Parameter name:SelectedIndex"
XAML is
<Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<Grid x:Name="itemGrid" DataContext="{Binding SelectedItem, ElementName=listBox}">
<Image Margin="185,56,153,160" Stretch="Fill" Source="{Binding Name}"/>
</Grid>
<ListBox x:Name="listBox" SelectedIndex="0" Margin="8,0,0,8" ItemsSource="{Binding Collection}" ItemTemplate="{StaticResource ItemTemplate1}" ItemsPanel="{StaticResource ItemsPanelTemplate1}" Height="101" VerticalAlignment="Bottom"/>
</Grid>
If I remove the selected index, all compile good. Could someone explain why it showed first time after compiling, it stopped working?
Thanks

You are almost always better binding to the SelectedItem than the SelectedIndex. If the Item is null, the binding should fail gracefully.

This is probably because the "Collection" attribute gets bound to the itemsource after the listbox is rendered. So if there is no collection(empty) then the first index [0] does not exist and it throws an "out of range exception".
To resolve your issue set the selected index in code-behind after collection is populated. Hope that helps.

Related

Xamarin Custom Control Command / CommandParameter question

I've been working on creating a custom control for some time. After several iterations I've come to the conclusion that I am having a binding issue... As it is, when I place my control into a simple XAML page and execute the feature, it works just fine. However, when I need to instantiate numerous controls on a single page, i.e. into a collection, flexlayout, carouselview the Command and CommandParameter bindings get lost... and the ViewModel calls no longer occur.
My control is simple... think of a checkbox replacement. I place A 1x1 grid, with a frame (for the outline) and a label to place a single character... "A", "B", "C"... "1". "2". "3"... whatever you would require... I have bindable properties.. Text, TextColor, BorderColor, BackgroundColor, and "Selected".
So, now I need to have a page ask the question... "How do you feel about... whatever... Pick all that apply." Then I provide a list... with number or lettered items... The user can select none, any, or all... So I create a view with a series of questions, that have a list of "checkable" items... As I said above, the control works perfectly if it is in a standalone page... If I generate a List of these controls dynamically, Command and CommandParameter suddenly no longer work.
my test implementation looks something like the following... although in this case think something much simpler like a "lottery ticket" number chooser. In this case the ViewModel would have a simple ObservableCollection<string> PrimaryControlList; And, the CommandParamter will call a VM function along with the text of the control in order to track the items the user has selected.
<Frame x:Name="primaryFrame">
<FlexLayout x:Name="flexPrimary" BindableLayout.ItemsSource="{Binding PrimaryControlList}" Wrap="Wrap" Direction="Row" JustifyContent="SpaceAround" AlignItems="Start" AlignContent="Start" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<local:NumberSelect Text="{Binding .}" Command="Binding DoSomethingWithThis" CommandParameter="{Binding .}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
</Frame>
Can anyone provide guidance?
The command is in your ViewModel while the current BindingContext of FlexLayout is PrimaryControlList.
Solution:
First, give a name to your ContentPage, let's say it MyPage:
<ContentPage 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:Name="MyPage"
x:Class="App266.MainPage">
Assume your page binds to a ViewModel and your binding of command should be:
<local:NumberSelect Text="{Binding .}" Command="{Binding BindingContext.ButtonCommand, Source={x:Reference MyPage}}" CommandParameter="{Binding .}"/>

WP7: Listbox item template doesn't work when edited?

**UPDATED**
Just something quick, hope you guys can help me but i'm having this problem where I open up my wp7 project in blend and i edit the listbox item template and i finish it but. I save everything and go back to VS2010 for Windows phone and hit debug but i look at the phone and i have no items showing up at all. The listbox is just blank.
Code:
<ListBox toolkit:TiltEffect.IsTiltEnabled="True" x:Name="ListBox1" FontSize="42.667" FontFamily="Segoe WP SemiLight" IsSynchronizedWithCurrentItem="False" d:LayoutOverrides="VerticalAlignment">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="sp">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="False" >
<toolkit:MenuItem Header="Delete" Click="Delete_Click" Name="MenuItem1" />
<toolkit:MenuItem Header="Edit" Click="Edit_Click"/>
<toolkit:MenuItem Header="View" Click="View_Click"/>
<toolkit:MenuItem Header="Share.." Click="Share_Click"/>
</toolkit:ContextMenu>
Quick Brief
The app I'm making is a simple note app which saves notes in to a folder in the isolated storage. It successfully retrieves the items but i just want to make it so that it has the title and a brief description. This is all in one item. I've got to that point and the 2 textblocks have ="{Binding}" this basically just adds the title I'm assuming but i also added the ="{Binding}" to the second textblock so its basically showing the title for both of them. Is there a way to bind it to a specific item? like the second textblock, how can i bind that so that it shows 1st 12 characters inside a text file so basically it just shows the title and a brief description?
Maybe you have designtime-only data?
In case you're using Mvvm Light DataService approach, you define 2 DataServices: one for designtime and another for realtime.
Just random assuming. it would be nice to see some sample.
UPD: you posted wrong code, this one is about ContextMenu. I dont see binding there.
But again, generally talking, there shouldnt be any problems. You just deserialize data into model, say
public class Note
{
public string Name {get; set; }
public string Content; {get; set; }
}
And then you have List (or even ObservableCollection if you want realtime changes like renaming). And then you just bind
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Content}"/>
If you want to have a strict limit for Content/Description of 12 characters, you can add either Converter and take only 12 first characters, or introduce new property
class Note
{
***
public string Description { get { return Content.Substring(0, 12); } }
}
UPD2:
Ok, lets start from the very beginning. First, MVVM is recommended pattern for Wp7 applications. I believe, you can google info about it yourself, but here are the most important parts:
Model. Keeps your data (in your case, it is notes names and description).
ViewModel. This is abstract view. You have all logic here, you have all data prepared to be rendered here, but VM have no idea how to render data. In your case, a list of notes would be here.
View. Here is description of your ui. In your case, ListBox would be here.
So, first, make a new project, then use NuGet to install latest Mvvm Light (for example). After installing, you should see folders for viewmodels and models.
Create new class Note, like i described before. It would be your model.
Now, go to viewmodel. In a constructor, add a list of Notes there, call it ListOfNotes. Add manually several items to the list and initialize them (add some random values for Names and Contents fields).
Now, go to view. In the top of the file, there should be something like DataContext = "{Binding MainViewModel, Source={StaticResource ViewModelLocator}}". Inside of the view, add ListBox. It should be something like
<ListBox ItemsSource="{Binding ListOfNotes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Content}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So, what would happen now. When you would run your app, your view would be initialized. It would get MainViewModel (because is it set as DataContext, in step 4). In the constructor of MainViewModel, a ListOfNotes would be initialized (see step 3). Then, when page would load ListBox, it would try to find ListOfNotes inside of DataContext (MainViewModel in our case). It should find your list of Notes, and then, every element of the ListBox would be associated with every element of your ListOfNotes. As it is described in DataTemplate, it would try to get Note.Name and Note.Content.

Caliburn micro and list picker control

I am trying to use the list picker control for wp 7 and caliburn micro. I get the binding correct from the model with conventions, but when I press the the picker to see the page to select somethin gelse I get the message
PID:0E2108CA TID:0F790ABE 2012-04-30 18:02:20.7180 View Model not found. Searched: Microsoft.Phone.Controls, Microsoft.Phone.Controls.ListPickerPageViewModel.
PID:0E2108CA TID:0F790ABE 2012-04-30 18:02:20.7210 View Model not found. Searched: Microsoft.Phone.Controls.IListPickerPageViewModel, Microsoft.Phone.Controls.ListPickerPageViewModel.
and it loads a complete blank page (think its the ListPickerPage in the control toolkit)
it doesnt matter if its bound or not, i guess its some convention hooking in that I dont want.
To reproduce start a new project, hoock up a viewmodel and view, enter below in in your xaml
my xaml looks like this
<toolkit:ListPicker Header="Background" ExpansionMode="FullscreenOnly">
<sys:String>dark</sys:String>
<sys:String>light</sys:String>
<sys:String>dazzle</sys:String>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="16 21 0 20">
<TextBlock Text="{Binding}"
Margin="0 0 0 0"
FontSize="43"
FontFamily="{StaticResource PhoneFontFamilyLight}"/>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
What I would like to happen is ofcourse that the property of my model should popuplate the fullscreen selection, and also it would be nice to set the initial selection based on a property on the model.
Some points I noted:
You have to provide an ItemsSource to the ListPicker - A collection of some sort from which it can display the items. In TextBlock text={Binding } - You have to bind some property, so that it can display.

Using a ListBox control in a DataTemplate

I have a simple WP7 Programm where I want to switch between displaying my model objects in a ListBox and a Diagramm.
I want to use Data Templates and a Selector Class which returns the correct template.
The selector takes a boolean property in the view model and returns ListBoxTemplate or DiagrammTemplate
My Page Resources looks like this:
<local:NewTemplateSelector x:Key="NewTemplateSelector">
<local:NewTemplateSelector.ListBoxTemplate>
<DataTemplate>
<StackPanel>
<ListBox
x:Name="MainListBox" Margin="6,205,35,136" ItemsSource="{Binding Acts}"
ItemTemplate="{Binding ElementName=Page, Path=Orientation,
Converter={StaticResource OrientationToListItemTemplate}}" />
</StackPanel>
</DataTemplate>
</local:NewTemplateSelector.ListBoxTemplate>
<local:NewTemplateSelector.DiagrammTemplate>
<DataTemplate>
<TextBlock Text="Diagramm"/>
</DataTemplate>
</local:NewTemplateSelector.DiagrammTemplate>
</local:NewTemplateSelector>
My content Panel has only 1 element:
<ContentControl ContentTemplate="{Binding IsDiagramm,
Converter={StaticResource NewTemplateSelector}}" HorizontalAlignment="Left" HorizontalContentAlignment="Left" />
I always get a blank screen when I run this.
My Selector class returns the correct template, I can see this in the debugger.
When I replace the Listbox in the template with a simple textblock, the textblock is displayed, so I suspect a problem with databinding.
But the listbox in the template works fine, when I insert it in my content panel without any data templates.
Any hints for me?
You may like to refer to this thread which discusses nested listboxes.
Listbox Inside listbox Databinding Problem

Extremely confused about ContentPresenter

FYI I'm pretty new to Silverlight.
Okay, so I want to build a simple user control that contains a button plus some additional XAML as specified by the client of the control.
I got searching on Google and found at least 30 different articles that were all very confusing; especially because they talk about styling animation, customizing other controls that you don't own, and other crap I'm not ready for yet.
This is what I did.
In VS 2010, I right clicked and added a new UserControl called MyControl
To the MyControl.xaml I changed the LayoutRoot to a StackPanel and added a Button inside it
In my MainPage.xaml I added an instance of MyControl
I added a TextBox as a child element of this instance
I tried to build and got an error that MyControl didn't support Direct Content
Googled some more..
I changed MyControl to inherit from ContentControl and updated the xaml
I added a ContentPresenter in the xaml to represent the client "custom content"
Okay, it builds and the TextBox shows up, but the Button is missing.
Here's the relevant section from MainPage.xaml
<my:MyControl HorizontalAlignment="Left" Margin="49,26,0,0" x:Name="myContentControl1" VerticalAlignment="Top" Height="550" Width="389">
<TextBox Height="72" HorizontalAlignment="Left" Margin="166,339,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="460" />
</my:MyControl>
Here's the MyControl.xaml
<ContentControl x:Class="ContentControlTest.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<StackPanel x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}" Orientation="Vertical">
<ContentPresenter/>
<Button Content="Button" Height="72" HorizontalAlignment="Left" Margin="78,254,0,0" Name="FooFoo" VerticalAlignment="Bottom" Width="160" />
</StackPanel>
</ContentControl>
And here is the MyControl.cs
using System.Windows.Controls;
namespace ContentControlTest
{
public partial class MyControl : ContentControl
{
public MyControl()
{
InitializeComponent();
}
}
}
The way I thought it worked was that the child elements of the control instance are set as the Content property on the ContentControl base class of MyControl. Then, ContentPresenter "pastes" that content into the MyControl.xaml wherever appears.
Although that does seem to be how it works, in the process it is "eating" the Button that I have defined in the MyControl.xaml.
I'm trying not to get into ControlTemplate etc that at this point unless it is absolutely necessary.
Can someone with a clue please tell me what I am doing wrong.
thanks!
That's because the Content of the control is the entire StackPanel you've written by hand; when you set a new Content, the StackPanel is replaced.
A ControlTemplate is necessary for this scenario, I think; it would be a very simple one after all. The starting point can be the default style of the content control; put the style inside a ResourceDictionary (for instance, in the <ContentControl.Resources> section of your user control), and you're ready to go; all you need to do is add a grid and button inside that template.
Note that the style I linked to sets itself as the default for any reachable ContentControl; to make it only apply to your control and not to any children that may appear inside it, add x:Key="someKey" to the Style and set the ContentControl's Style property explicitly to Style={StaticResource someKey}.
Let me know if you need additional information; also, I might be wrong and there may be an easier way, but I doubt it; the Content property is meant to behave exactly like what you described.

Resources