Metro App ListView SelectedItem Selected VisualState - windows-runtime

I have a Metro App with a ListView that contains this definition:
<ListView Grid.Row="0" x:Name="lv" CanDragItems="True" CanReorderItems="True" IsTabStop="True" SelectionMode="Extended" VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="{Binding ElementName=lv, Path=ActualWidth}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="65"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="tb1" Foreground="{StaticResource SecondaryColourBrush}" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Column="4" x:Name="tb2" Foreground="{StaticResource SecondaryColourBrush}" HorizontalAlignment="Right"/>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="65"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="tb3" Foreground="{StaticResource QuadColourBrush}" HorizontalAlignment="Stretch" TextTrimming="WordEllipsis"/>
<TextBlock Grid.Column="1" x:Name="tb4" Foreground="{StaticResource QuadColourBrush}" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When the ListView has an item selected, I want to change the Foreground of tb1 and tb2 ONLY to White. How do I go about doing this?
I tried overriding Themed Brushes and VisualStateGroup SelectionStates for Selected, which hasn't helped. A working code example would be appreciated.

Finally RESOLVED this, thanks to this article for giving me the idea:
http://blog.davemdavis.net/2012/11/12/controlling-the-datatemplate/
Created a BooleanToColourConverter
public sealed class BooleanToColourConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return (value is bool && (bool)value) ? AppResources.TertiaryColourBrush : AppResources.PrimaryColourBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value is SolidColorBrush && ((SolidColorBrush)value).Color == AppResources.TertiaryColourBrush.Color;
}
}
Added this in App.xaml
<common:BooleanToColourConverter x:Key="BooleanToColourConverter"/>
Then used it like this:
Foreground="{Binding Tag, Converter={StaticResource BooleanToColourConverter}, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"

Related

String returning null

I am facing issues getting the string values using e.ClickedItem.
Here's how my ListView looks like:
<ListView
x:Name="PoemListView"
AutomationProperties.AutomationId="PoemListView"
AutomationProperties.Name="Poems In Item"
TabIndex="1"
ItemsSource="{Binding Item.Poems}"
IsItemClickEnabled="True"
ItemClick="PoemView_PoemClick"
SelectionMode="None"
SelectionChanged="PoemSelectionChanged"
IsSwipeEnabled="False" Padding="0,0,0,0" Margin="0,0,0,0"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="0,0,0,27.5" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<!--<CheckBox x:Name="PoemCheckbox" Checked="ContentChecked" Unchecked="ContentUnchecked"/>-->
<TextBlock x:Uid="PoemId" Name="PoemId" Text="{Binding PoemId}" DataContext="{Binding}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" TextWrapping="WrapWholeWords"/>
<TextBlock x:Uid="PoemTitleId" Text="{Binding PoemTitle}" FontSize="{Binding ElementName=FontSlider, Mode=OneWay, Path=Value}" DataContext="{Binding}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" Foreground="{ThemeResource PhoneMidBrush}" TextWrapping="WrapWholeWords"/>
<TextBlock x:Uid="PoemMeanId" Text="{Binding PoemMean}" DataContext="{Binding}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" TextWrapping="WrapWholeWords"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is the code behind the xaml page:
private void PoemView_PoemClick(object sender, ItemClickEventArgs e)
{
TextBlock PoemId = e.ClickedItem as TextBlock;
this.Frame.Navigate(typeof(Favorite), (e.ClickedItem as TextBlock));
On LoadState event of the Favorite page, I have added the below code:
private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
string poem = e.NavigationParameter as string;
if (string.IsNullOrEmpty(poem))
{
FavText.Text = "no favorite text";
}
else { FavText.Text = poem;
}
}
The problem is in the LoadState while the e.NavigationParameter is loaded with the strings passed to it, the string poem is not loading properly. Therefore, the FavText.Text is always returning the "no favorite text".
Anyone has a clue on how to fix this?
Your PoemId is probably null when you cast e.ClickedItem as TextBlock
Try this
Poem poem = e.ClickedItem as Poem;
this.Frame.Navigate(typeof(Favorite), poem);
Instead of casting e.ClickedItem as TextBlock, I updated the code as below which worked perfectly fine:
var type = ((PoemItem)e.ClickedItem).PoemTitle;
this.Frame.Navigate(typeof(Favorite), type);

ScrollViewer scroll to specific control

I have a scrollviewer with an item template on it. the user sends a control number and I need to scroll to that item. How can I find the offset for the scrollviewer?
here is the scrollviewer that I am using
<ScrollViewer Grid.Row="0" x:Name="ScrollPanel" Padding="0">
<Grid x:Name="TestPanel" >
<ItemsControl x:Name="MainItemsControl" ItemsSource="{Binding PostList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="PostPanel" Margin="0,5,0,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image x:Name="IconUrl" Source="{Binding IconUrl}" Grid.Row="0" Grid.Column="0" Margin="12,0,12,0" VerticalAlignment="Center" HorizontalAlignment="Center" Width="50"/>
<StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock x:Name="PostAuthorName" Text="{Binding PostAuthorName}" TextWrapping="NoWrap" Margin="12,0,12,0" Foreground="Black" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PostTime" Text="{Binding PostTime}" TextWrapping="NoWrap" Margin="12,0,12,0" Foreground="Black" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
<TextBlock x:Name="ReplyNumber" Text="{Binding ReplyNumber}" Grid.Row="0" Grid.Column="2" TextWrapping="NoWrap" Foreground="Black" Margin="12,0,12,0" Style="{StaticResource PhoneTextNormalStyle}" VerticalAlignment="Center"/>
</Grid>
<RichTextBox x:Name="PostContent" localcontrols:Properties.BBCode="{Binding PostContent}" />
<Rectangle Grid.Row="1" Fill="Gray" Height="1" HorizontalAlignment="Stretch" Margin="0,10,0,10"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>
The offset can be calculated in this way. The code is adopted from this answer.
void ScrollToIndex(int index)
{
var itemContainer = MainItemsControl.ItemContainerGenerator.ContainerFromIndex(index) as UIElement;
GeneralTransform transform = itemContainer.TransformToVisual(ScrollPanel);
Point position = transform.Transform(new Point(0, 0));
ScrollPanel.ScrollToVerticalOffset(position.Y);
}
The ItemsControl does not implement logic that allows scrolling to a particular item. You can use the ListBox control instead. This control has a ScrollIntoView method that accepts the object you would like to scroll to as an argument. You can still use the RadWrapPanel by setting the ItemsPanel property of the ListBox control.
You don't have properties, but you have two methods for this: ScrollToVerticalOffset (to scroll vertically) and ScrollToHorizontalOffset (to scroll horizontally).
this.scrollViewer2.ScrollToVerticalOffset(0);

How to create table structure in windows phone 8 app?

I want to create report of students in windows phone 8 app.
there are 3 row and 4 columns
structure is like as follow
student1 student2 student3
subject1
subject2
subject3
Total
marks
now the student1, student2 are names of student should come dynamically from windows azure database.
all the marks are in database for perticular students. these marks should get display in front of perticular student for perticular subject.
All data is present in database. How to show it in table form?
I think a simple Grid control containing some textblocks would be just fine. You can define it in XAML really easily:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" ... />
<TextBlock Grid.Row="1" Grid.Column="0" ... />
<TextBlock Grid.Row="2" Grid.Column="0" ... />
...
</Grid>
The only think you need to look out for is how the heights and widths are defined. Essentially there are 3 types of height/width:
Static: Defined with a number and measured in pixels
Automatic: Defined by the keyword Auto and changes dynamically according to content size
"Fill the rest": Defined by the star * symbol and makes the row/column fill the rest of the space available in the grid.
Check out the MSDN documentation for the Grid control for more info.
You can set View as Shown Below:
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox x:Name="stu" Grid.RowSpan="4" Grid.Column="1" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<TextBlock Text="{Binding name}"></TextBlock>
<TextBlock Text="{Binding s1}" TextAlignment="Center"></TextBlock>
<TextBlock Text="{Binding s2}" TextAlignment="Center"></TextBlock>
<TextBlock Text="{Binding s3}" TextAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock></TextBlock>
<TextBlock Grid.Row="1" Text="Subject1"></TextBlock>
<TextBlock Grid.Row="2" Text="Subject2"></TextBlock>
<TextBlock Grid.Row="3" Text="Subject3"></TextBlock>
</Grid>
CS:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<data> obj = new List<data>();
obj.Add(new data("Student1", "10", "20", "30"));
obj.Add(new data("Student2", "0", "10", "20"));
obj.Add(new data("Student3", "20", "30", "40"));
obj.Add(new data("Student4", "30", "40", "50"));
obj.Add(new data("Student5", "40", "50", "60"));
stu.ItemsSource = obj;
}
public class data
{
public string name { get; set; }
public string s1 { get; set; }
public string s2 { get; set; }
public string s3 { get; set; }
public data() { }
public data(string name, string s1, string s2, string s3)
{
this.name = name;
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
}
}
Here You just needed to have data from Azure Database. from above implementation you can have view like as under with scrolling data of Students.
You Have to Use 1st Listbox As Column and Set ItemSource Property
and
another ListBox For the Row of the Object and set ItemSource Property.

How to bind data user control inside listbox

I am trying to bind user control inside listbox, but it seems I am doing something wrong, Though I followed How to bind data user control inside listbox WP8 but this couldn't help.
Here what I am doing in user control
<Grid x:Name="LayoutRoot" Background="Transparent" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="Images/download.png" Width="30" Height="30" VerticalAlignment="Top" Grid.Column="0"/>
<ProgressBar Grid.Row="0" Grid.Column="1" x:Name="prg" VerticalAlignment="Top" />
<TextBlock x:Name="TextBlock" Foreground="Black" Text="{Binding Text}" Grid.Row="0" Grid.Column="2" VerticalAlignment="Top" FontSize="20" HorizontalAlignment="Left" />
</Grid>
and code behind for user control
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(SuraWithProgressBar),
new PropertyMetadata(null));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value);}
}
The usage
<ListBox x:Name="lsbQuranData" Grid.Row="1" Foreground="Black" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<local:SuraWithProgressBar Text="{Binding SuraTName, ElementName=SuraWithProgressBar}"></local:SuraWithProgressBar>
<Line X1="0" X2="480" Y1="0" Y2="0" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="Black" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and code behind for usage
lsbQuranData.ItemsSource = App.Chapter;
Let me mention that "App.Chapter" contain "SuraTName" which is binded to Text property of user control. The user control is added in list box, but the text is not displayed.
Converter is a good thing for debug binding issue =>
public sealed class DebugConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
Finally, I came up with following solution.
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(SuraWithProgressBar),
new PropertyMetadata(null));
I changed the "Text" to "SuraTName" and it worked!!

Windows Phone 8: LongListMultiSelector not scrollable

<StackPanel x:Name="LayoutRoot" Background="Transparent" >
<TextBlock Margin="20,20,0,0" Text="Type Text Here" HorizontalAlignment="Left"/>
<TextBox x:Name="SearchTextBox" IsReadOnly="False" HorizontalAlignment="Left" Margin="20,5,0,0" Height="70" Width="400" dp:TextBoxOnTextChangedDependency.UpdateSourceOnChange="True" Text="{Binding SearchBoxText, Mode=TwoWay}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<cmd:EventToCommand PassEventArgsToCommand="True"
Command="{Binding ElementName=SearchTextBox, Path=DataContext.SearchTextBox_TextChangedCommand}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<Grid x:Name="LayoutList" Background="{StaticResource PhoneChromeBrush}">
<toolkit:LongListMultiSelector x:Name="treksLocationItems" Background="Transparent"
ItemsSource="{Binding Path=TreksLocationItems}">
<toolkit:LongListMultiSelector.ItemTemplate>
<DataTemplate>
<Grid Margin="0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Width="110" Height="150" Source="{Binding PictureFilename}" VerticalAlignment="Top"/>
<StackPanel Grid.Column="1" VerticalAlignment="Top">
<TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextLargeStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Margin="12,-12,12,6"/>
<TextBlock Text="{Binding ShortDescription}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Address:" Style="{StaticResource PhoneTextSmallStyle}"/>
<TextBlock Text="{Binding Path=StreetName}" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Site:" Style="{StaticResource PhoneTextSmallStyle}"/>
<TextBlock Text="{Binding Path=Website}" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
</StackPanel>
</StackPanel>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<cmd:EventToCommand Command="{Binding Path=DataContext.TapCommand, ElementName=searchItems}" CommandParameter="{Binding Path=Id}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</DataTemplate>
</toolkit:LongListMultiSelector.ItemTemplate>
</toolkit:LongListMultiSelector>
</Grid>
</StackPanel>
I have this code in XAML, a textbox for search and a multi line select list. The problem is that the multiLineList is not scrollable even if there are many items. If I remove the stackpanel and the textblock and textbox, the list works ok with scroll enabled. Any suggestion?
Try adding a ScrollViewer above your grid.
<ScrollViewer>
<Grid x:Name="LayoutList" ....>
...
</Grid>
</ScrollViewer>
Or you could probably replace your Grid with a ScrollViewer if you're not using it to position your elements.
Wraping LLMS in a ScrollViewer will destroy the item virtualization and throw an OutOfMemoryException if the collection is too long.
Expose the LLMS' inner LongListSelector, then use the ScrollTo() method to scroll to the item u want.
LongListMultiSelector llms = LongListMultiSelector as LongListMultiSelector;
if (llms != null && llms.ItemsSource.Count > 0)
{
llms.InnerLongListSelector.ScrollTo(llms.ItemsSource[llms.ItemsSource.Count - 1]);
}
I've encountered this weird issue and found an easy solution.
It happens for both Longlistselector and LonglistMultiselector.
When you have several controls in one page, you need to set the height of selector's row to "*" instead of "Auto" in order to make the scrolling function to work correctly.
For example :
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> //Row def for another row
<RowDefinition Height="*"/> //Row def for your selector
</Grid.RowDefinitions>
If the RowDefinition Height not set to "*" but "Auto", scrolling for Longlistselector will not response to user's action.