How to Scroll into selected item in listbox - c#

I am really confused with wp8 listbox scrolling. with below simple code I am scrolling to the selected index (item), but it doesn't work.
lsbReadingChapter.SelectionChanged -= lsbReadingChapter_SelectionChanged;
_lastAyaSelectedIndex = startingAya;
lsbReadingChapter.ItemsSource = null;
lsbReadingChapter.ItemsSource = ds.getArabicTextWithTranslation(currentChapter);
lsbReadingChapter.SelectedIndex = startingAya;
lsbReadingChapter.UpdateLayout();
lsbReadingChapter.ScrollIntoView(lsbReadingChapter.SelectedItem);
lsbReadingChapter.SelectionChanged += lsbReadingChapter_SelectionChanged;
the selectedIndex is always greater than zero, but the listbox show the 1st item in the list and doesn't scroll.
Here is my xaml
ListBox x:Name="lsbReadingChapter" HorizontalAlignment="Stretch" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="480" SelectionChanged="lsbReadingChapter_SelectionChanged" Loaded="lsbReadingChapter_Loaded">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Stretch" Width="480" Orientation="Vertical" Background="{Binding Converter={StaticResource AlternateRowConverter}}" >
<TextBlock Foreground="Black" Padding="20,0,30,0" TextWrapping="Wrap" HorizontalAlignment="{Binding HAlignment}" FontSize="{Binding ArabicFontSize}">
<Run Text="{Binding Aya}"/>
<Run Text="{Binding AyaID, StringFormat=﴿\{0\}﴾}" Foreground="Blue" FontSize="30"/>
</TextBlock>
<TextBlock Padding="20,0,30,0" Text="{Binding AyaTranslation}" Foreground="Black" FontSize="{Binding TranslationFontSize}" TextWrapping="Wrap" HorizontalAlignment="{Binding HAlignment}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I don't know why it doesn't scroll to the selected index?
Thanks!

Use ScrollIntoView function either by SelectedIndex or SelectedItem property.
lsbReadingChapter.ScrollIntoView(lsbReadingChapter.SelectedIndex);
or
lsbReadingChapter.ScrollIntoView(lsbReadingChapter.SelectedItem);

public static void ScrollToSelectedItem(ListBox control)
{
if (control.SelectedIndex != -1)
control.TopIndex = control.SelectedIndex;
}

Use
lsbReadingChapter.ScrollIntoView(lsbReadingChapter.Items[lsbReadingChapter.SelectedIndex]);

finally solved, by calling lsbReadingChapter.ScrollIntoView in grid load parent of Lisbox.

Related

How to change the background color of TreeViewItem when clicking in the WPF treeview?

I want to change the background of StackPanel when clicking TextBlock.
enter image description here
now background is bule! I want to change it!
<TreeView Name="tvView" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ChildNodes}">
<Grid VerticalAlignment="Top" Margin="0">
<StackPanel Orientation="Horizontal" d:LayoutOverrides="Height">
<TextBlock Name="ConfidenceLevelReminderText" Text="!" FontWeight="Bold" HorizontalAlignment="Center" Foreground="#FF0000" Width="{Binding Path=ConfidenceLevelWidth}" Margin="0,0,0,0"></TextBlock>
<TextBlock TextWrapping="Wrap"
Padding="0,3,0,3"
Text="{Binding Path=Name}"
ToolTip="{Binding Path=NameToolTip}"
Tag="{Binding Path=TagInfo}"
MouseLeftButtonDown="name_MouseLeftButtonDown"
FontSize="14"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="#FF666666"
Margin="0"
Width="{Binding Path=TextWidth}"
Cursor="Hand"/>
<Button x:Name="btnIngnore" Width="{Binding Path=IgnoreWidth}" Click="btn_ignore_Click" Tag="{Binding Path=NodeId}" Margin="0" BorderThickness="0" Background="{x:Null}" Style="{StaticResource ButtonStyle32}" IsEnabled="{Binding Path=IgnoreWidth,Converter={StaticResource itb}}" Cursor="Hand">
<TextBlock Text="xxxx" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" FontSize="12" Foreground="#FF666666"/>
</Button>
</StackPanel>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
If you want
to change the background of StackPanel when clicking TextBlock.
You can add EventSetter to the TextBlock's Style and handle event in the event handler.
<TextBlock Text="...">
<TextBlock.Style>
<Style TargetType="TextBlock">
<EventSetter Event="MouseDown" Handler="Mouse_LBtnDown"/>
</Style>
</TextBlock.Style>
</TextBlock>
private void Mouse_LBtnDown(object sender, MouseButtonEventArgs e)
{
StackPanel stp = null;
var visParent = VisualTreeHelper.GetParent(sender as FrameworkElement);
while (stp == null && visParent != null)
{
stp = visParent as StackPanel;
visParent = VisualTreeHelper.GetParent(visParent);
}
if (stp == null) { return; }
stp.Background = Brushes.Coral;
}
For make it reusable and adjustable you could make a behavior from the event handler.
If you don't want what you have asked, then rethink your question and ask new one.

Combo box add item from template

Im trying to add items to the combo box from the code behind to the item template but im getting null. This is what I have so far:
XAML:
<ListBox x:Name="lsbCiertoYFalsoInsideTemplate" Margin="40,0,0,0" ItemTemplate="{StaticResource CiertoYFalsoExcerciseDataTemplate}"/>
App.xaml:
<DataTemplate x:Key="CiertoYFalsoExcerciseDataTemplate">
<Grid>
<StackPanel x:Name="stckCiertoYFalsoInsideTemplate" Margin="0" Orientation="Vertical" Width="1100">
<StackPanel x:Name="stckPreguntasCiertoYFalso" Orientation="Horizontal">
<Grid Height="50" Width="65" DataContext="{Binding CustomValueList}" VerticalAlignment="Top">
<ComboBox x:Name="cbExercises" Style="{StaticResource SA_ComboBoxStyle}" ItemsSource="{Binding CustomOption}" BorderBrush="#CC8C8C8C" VerticalAlignment="Top">
</ComboBox>
</Grid>
<TextBlock HorizontalAlignment="Center" Margin="5,3,0,0" TextWrapping="Wrap" Text="{Binding QuestionNumber}" VerticalAlignment="Top" FontWeight="Bold" Foreground="Black" Width="26" FontFamily="{Binding FontFamily, Source={StaticResource TextBlockStyleManager}}" FontSize="{Binding FontSize, Source={StaticResource TextBlockStyleManager}}"/>
<TextBlock TextWrapping="Wrap" Text="{Binding Question}" Foreground="Black" VerticalAlignment="Top" FontSize="{Binding FontSize, Source={StaticResource TextBlockStyleManager}}" Margin="10,3,0,0" Width="968" FontFamily="{Binding FontFamily, Source={StaticResource TextBlockStyleManager}}"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
The error im getting is object out of range.
Code:
private void ComboBoxExercises()
{
ComboBox comboBox = new ComboBox();
ComboboxItem item = new ComboboxItem();
item.Text = "A";
comboBox = (ComboBox)lsbCiertoYFalsoInsideTemplate.FindName("cbExercises");
comboBox.SelectedIndex = 0;
comboBox.Items.Add(item);
}
public class ComboboxItem
{
public string Text { get; set; }
public override string ToString()
{
return Text;
}
}
There's a disconnect in what you're trying to do here. You've specified an ItemTemplate - which defines how each item in the list will look.
But then you're trying to get one single ComboBox back out via the FindName function. Which leads me to believe that you're really intending to set the Template, not the ItemTemplate.
That said, I think the error you're getting is because you're setting the SelectedIndex to 0 when the ComboBox has no items in it. You're telling it to select the first one, but there's nothing to select. You should add the item first, then select it.

Focus on first item of first LongListSelector within a Pivot

I have a report to fill in that is made up of a List of sections, each of which has a List of questions. My current implementation uses a Pivot control whose ItemsSource is set to the List of sections and DataTemplate is a LongListSelector whose ItemsSource is set to the List of questions.
When the user attempts to submit the report, I loop through all the questions to check their validity. If any come back invalid, a flag is set and an error message is shown next to that question.
I would like to be able to focus on the first question that has that flag set but cannot figure out how to obtain a reference to the required LongListSelector so that I can call it's ScrollTo method.
Code:
View
<phone:Pivot toolkit:TurnstileFeatherEffect.FeatheringIndex="0"
Name="QuestionPivot"
ItemsSource="{Binding Sections, Mode=TwoWay}">
<phone:Pivot.Title>
<TextBlock>
<Run Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"/>
<Run Text=" "/>
<Run Text="{Binding Path=LocalizedResources.DailyReport, Source={StaticResource LocalizedStrings}}"/>
<Run Text=" - "/>
<Run Text="{Binding ProjectName}"/>
</TextBlock>
</phone:Pivot.Title>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding SectionName}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<phone:LongListSelector ItemsSource="{Binding Questions, Mode=TwoWay}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 0 0 20">
...
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
Code Behind (including my failed attempt to cast the SelectedItem to a LongListSelector...)
private void FocusOnFirstInvalid(object sender, EventArgs e)
{
int selectedItem = 1;
foreach (ReportDraftSection s in QuestionPivot.Items)
{
foreach(ReportQuestion q in s.Questions)
{
if(q.IsNotValid)
{
QuestionPivot.SelectedIndex = selectedItem;
var l = (LongListSelector)QuestionPivot.SelectedItem;
l.ScrollTo(q);
}
}
selectedItem += 1;
}
}
Any help would be greatly appreciated.
Since Pivot's ItemsSource is a List of Section, QuestionPivot.SelectedItem contains a Section object instead of LongListSelector. You can try to use ItemContainerGenerator to get PivotItem from SelectedItem, then get LongListSelector from PivotItem's Content (not tested yet) :
.......
QuestionPivot.SelectedIndex = selectedItem;
var pivotItem = (PivotItem)QuestionPivot
.ItemContainerGenerator
.ContainerFromItem(QuestionPivot.SelectedItem);
var l = (LongListSelector)pivotItem.Content;
l.ScrollTo(q);
.......

Make filter on wpf Listbox with Item template

I have a listbox in WPF databinded to a observablecollection
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding ShopList}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Grid.Row="1"
Grid.ColumnSpan="2" KeyDown="ListBox_KeyDown" KeyUp="ListBox_KeyUp"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17" >
<!--Replace rectangle with image-->
<Rectangle Height="50" Width="50" Stroke="Black" StrokeThickness="6" Margin="12,0,9,0"/>
<StackPanel Width="Auto">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Quantity}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I then have a filter method I want called
private void ShopItemDay_Filter(object sender, FilterEventArgs e)
{
var item = e.Item as ShopItem;
e.Accepted = item.Day == 1;
}
But I cant find any properties on the Listbox to use a filter method like done here http://www.galasoft.ch/mydotnet/articles/article-2007081301.aspx
You need to create a 'view' on your collection. See the documentation for CollectionView.Filter. The framework will create a default view for all bound collections. You can add a filter as follows:
ICollectionView _customerView = CollectionViewSource.GetDefaultView(customers);
_customerView.Filter = CustomerFilter
private bool CustomerFilter(object item)
{
Customer customer = item as Customer;
return customer.Name.Contains( _filterString );
}
(From this tutorial);
As you can see in the article you linked to, the filter is not a property of the Control. It is a property of the CollectionViewSource which is a kind of wrapper around the collection. This wrapper allows for sorting, grouping and filtering.

accessing an item variable from dynamic data in listbox on SelectionChanged

I am populating a listbox from a webcclient, the data is binded to the listbox and not saved anywhere..
Id like to access binded information when the user selects from the listbox
im having trouble accessing the value of a text block from the SelectionChanged event..
<ListBox x:Name="UsersListBox" ItemsSource="{Binding Items}" Height="471" VerticalAlignment="Top" HorizontalAlignment="Left" Width="457" SelectionChanged="TargetsListBox_SelectionChanged" Grid.ColumnSpan="2">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Orientation="Horizontal">
<Image x:Name="ImageAddIcon" Source="blkAdd.png" Height="60" Width="71" VerticalAlignment="Stretch" />
<Image x:Name="ImagePointer" Source="blkClick.png" Height="60" Width="71" VerticalAlignment="Stretch" />
<StackPanel>
<TextBlock Name="txtID" Text="{Binding PlayerID}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="#FF8A9A8A" Visibility="Collapsed" />
<TextBlock Name="txtNick" Text="{Binding Nickname}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="#FF8A9A8A" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Id like to access the PlayerID from this dynamicly populated list(from webservice) on a onselected basis
private void TargetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string ID = UsersListBox.SelectedItem ???PlayerID or txtID???;
}
i just want to get the player id that is binded to the listbox with a selection changed event ANY IDEAS!!!!!!!!! <3
Assuming that "Items" is a ObservableCollection:
private void TargetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
var selectedItem = listBox.SelectedItem as Player;
if (selectedItem != null)
{
string id = selectedItem.PlayerID
string nick = selectedItem.NickName;
}
}

Categories