WPF ListView Always focused last added item? - wpf

I have many ListViews with the same DataSource with IsSynchronizedWithCurrentItem="True"
and I'm dynamicaly adding items to this DataSource.
The problem ist when the scrolls appears, the added items are not visible unless I move the scrollbar. Should I use another Control for this purpose.. or how can bring the last added item into view (and scrollbars).
Until now I was doing everything directly in XAML, so I'd appreciate such a solution if possible.

if ( !(myListView.Items.IsEmpty) )
{
myListView.ScrollIntoView(myListView.Items[myListView.Items.Count - 1]);
}
Hope that helps!

I think you may need to use the method:
ListView.ScrollIntoView(ListView.SelectedItem);

I come with a solution:
It cannot be applied in all cases, but it this one it's sufficient!
The trick is to
disable the ListView ScrollBars and surround it with the ScrollViewer.
...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" /> <!-- This is needed! -->
...
</Grid.RowDefinitions>
..
<ScrollViewer x:Name="MyScrollViewer" Grid.Row="0" >
<ListView Name="MyListView"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
ScrollViewer.VerticalScrollBarVisibility="Disabled" />
</ScrollViewer>
...
</Grid>
Then simply if needed call
MyScrollViewer.ScrollToEnd();

That sounds suspicious, but even if it's true, you can always call ListView.BringIntoView() method, to... bring selected item into view :).

Related

WPF control alignment is wrong when dynamically added

Hi I thought I could solve this easily but it is driving me crazy.
I am using a UserControl to house a video player control based on VLC, along with play and stop buttons etc. I then place the UserControl on my main form. if the UserControl is declared in XAML it behaves normally.
I decided to rewrite the code to instantiate my UserControl dynamically, in case I need to destroy it and create another on the fly. But when I do the video moves to the top of its container instead of the middle.
The UserControl relevant section is here:
<Grid x:Name="LayoutParent" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
</Grid.RowDefinitions>
<!-- I comment this if adding player dynamically -->
<!--<wpf:VlcPlayer Grid.Row="0" x:Name="Player" />-->
<!-- I un-comment this if adding player dynamically -->
<Grid x:Name="VideoPlayerPanel" Grid.Row="0" Margin="0" />
<StackPanel Grid.Row="1" Opacity="0.8">
...(buttons etc)
</StackPanel>
<ProgressBar ...(progressBar etc) />
</Grid>
My codebehind looks like this:
Dim Player As VlcPlayer = New VlcPlayer ' uncomment If adding the player dynamically
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Player.SetValue(Canvas.ZIndexProperty, -1)
VideoPlayerPanel.Children.Add(Player)
VolumeSlider.Value = 50
End Sub
I have tried VerticalAlignment="Center" and VerticalAlignment="Stretch" in XAML on the VideoPlayerPanel, with Center the video disappears entirely, with Stretch it still aligns to the top.
Any thoughts as to what I might do to align this centrally would be much appreciated!
When adding Player dynamiccaly you have different result, because you wrap Play in additional Grid. Try to add Player directly to first row of LayoutParent:
Player.SetValue(Grid.Row, 0)
LayoutParent.Children.Add(Player)
Thanks to all that replied.
I did some more research, I substituted in a Rectangle for the player control and it aligned perfectly. That led me to discover that the third party control was itself at fault. I had to get the source and change the VerticalAlignment directly.
Sorry for the runaround.
Remove Height="*" from first Row . * is used to occupy remaining space, so it is good to use it for the last Row.
Use fixed width and or Auto.

How to create Carousel like control?

I need a "Сarousel like" control in my windows phone 7 APP, there will be list of images and I need to switch them like items in Pivot. What control should I use? Pivot is very similar, but I need footer in my application.
If you(or anyone else stumbeling into this question hunting for fancy UI elements) want it a bit more fancy you could alternatively use the Silverlight Flow Layouts Library which is a very powerfull carousel system with a dedicated WP7 binary. I have not used this on WP7 yet my self, but I have used it with WPF and it both looks good and performs well.
You can use a Pivot control where you hide the headers, I blogged about a simple solution to this problem here:
A Windows Phone 7 Slide View with Page Pips
You can add your fixed footer under the Pivot control as follows:
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="#EAE5C7">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<local:PivotLocationView Source="{Binding ElementName=pivot}"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Margin="0,0,0,10"/>
<controls:Pivot Margin="0,-30,0,40"
x:Name="pivot">
<controls:PivotItem>
...
</controls:PivotItem>
<controls:PivotItem>
...
</controls:PivotItem>
<controls:PivotItem>
...
</controls:PivotItem>
</controls:Pivot>
<!-- your fixed footer goes here -->
<Grid x:Name="footer" Grid.Row="1">
</Grid>
</Grid>
You can try to use the control from this Codeplex project Silverlight Carousel Control
and hope it does not use any non-WP7 features.

W7P ListBox doesn't stay scrolled in the emulator

I have a ListBox in a xaml page for a Windows Phone 7 app. It starts out empty, then I populate it with some items once they are retrieved from a web service. So far that all works fine - the items show up in the list and all seems fine. The problem I have is when I try to drag the list to scroll to the bottom (in the emulator): I can scroll down, but as soon as I release the mouse button the list springs back to the top as though I hadn't scrolled it at all. Any insights into why it would behave this way?
<Grid x:Name="ContentPanel" Grid.Row="2" Margin="0,0,0,0" Canvas.ZIndex="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <!-- EDIT: the problem was "Auto" here should have been "*" -->
</Grid.RowDefinitions>
<!-- removed other element for brevity -->
<ListBox Name="InfoBoardListBox" Grid.Row="1" SelectionChanged="InfoBoardListBox_SelectionChanged"
Margin="0,0,0,0" FontSize="26.667" />
</Grid>
And the method that populates the list:
foreach (InfoBoard entry in boards.Values) {
item = new ListBoxItem();
item.Content = entry.Name;
item.Name = entry.Id.ToString(); //used to tell which entry was clicked
InfoBoardListBox.Items.Add(item);
}
Try setting the Height of the second row to * instead of Auto; I think it's to do with the size that the ListBox thinks it is vs. the available space.

Detect which element scrollbars belong to

I have a relatively complex layout. It consists of:
A grid with one column and three rows.
In the first row (the on giving me trouble) I have a developer express componenet - another GridControl.
My problem is, that though the height of this first row is Auto, the vertical scrollbar displays even though there's space enough for content.
I've tried setting the ScrollViewer.VerticalScrollBarVisibility="Hidden" on the row's rowdefinition, but this doesn't help.
Likewise, I've set the inner GridControl to not use scrollbars (using some Developer Express magic - not just ScrollViewer as this doesn't work)
Yet, no matter what I do, that damn scrollbar appears... Is there any way to figure out which control renders it, so I can disable the damn thing? It's not just a question of it being ugly - scrolling it actually messes with the layout!
Thanks in advance!
The relevant code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" ScrollViewer.VerticalScrollBarVisibility="Hidden" />
<RowDefinition Height="*" MaxHeight="240" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<dxg:GridControl Name="StudySizeGrid" Grid.Column="0" Grid.Row="0" >
<dxg:GridControl.Resources>
<ControlTemplate x:Key="{dxgt:TableViewThemeKey ResourceKey=ControlTemplate}">
<ScrollViewer x:Name="scr"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"
Focusable="False"
dxg:GridControl.CurrentView="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Template="{DynamicResource {dxgt:TableViewThemeKey ResourceKey=ScrollViewerTemplate}}">
<ScrollViewer.CanContentScroll>False</ScrollViewer.CanContentScroll>
</ScrollViewer>
</ControlTemplate>
</dxg:GridControl.Resources>
...
</dxg:GridControl>
EDIT FOR CLARIFICATION: This is WPF issue :-)
You could try checking out the VisualTree, i think Snoop might be helpful for that, it probably has some other useful features too. Getting the VisualTree is a trivial matter though, you can write a single recursive method using the VisualTreeHelper, so you might not need the big guns.
e.g.
public static TreeViewItem GetVisualTree(this DependencyObject dpo)
{
TreeViewItem item = new TreeViewItem();
item.Header = dpo.GetType().ToString().Split('.').Last();
if (dpo is FrameworkElement && (dpo as FrameworkElement).Name != string.Empty) item.Header += " (" + (dpo as FrameworkElement).Name + ")";
int cCount = VisualTreeHelper.GetChildrenCount(dpo);
for (int i = 0; i < cCount; i++)
{
item.Items.Add(VisualTreeHelper.GetChild(dpo, i).GetVisualTree());
}
return item;
}
Wrote that quite some time ago, it's very sketchy (wouldn't recommend making it an extension method), gets the whole tree at one, could be modified to only fetch children on expansion of the node.
You could use something like Google Chrome's tools.
I would, in Chrome, right click around the area that has the scroll bars and select "Inspect Element". Chrome will highlight with a border what element you are looking at. You can then navigate the html within Google Chrome's inspector until it is highlighting the element with the scrollbar.
You can then find the reason from there.

how can i add a row dynamically in WPF?

I need to create a row in XAML which has a label,two radio buttons.. Based on some operation i need these row to be visible..else i need it to hidden.. I do not want the empty space to be displayed.. Is this possible only through code? If so can anyone help me out please?
Place the row in a grid and set it's height set to 'Auto'. Place your controls in a grid (or other container) and set it's Visibility to Collapsed for not visible and Visible for when you need to show it.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
...
<RowDefinition Height="Auto" /> <!-- Your 'hidden' row -->
...
</Grid.RowDefinitions>
<!-- your collapse content -->
<Grid Grid.Row="2" Visible="Collapsed" x:Name="hiddenRow">
....your controls...
</Grid>
</Grid>
Then to show the controls...
hiddenRow.Visible= Visibility.Visible;
Hope that helps....
What do you mean by "row"? A DataGridRow? An item in a vertical StackPanel?
Is this row part of a DataTemplate for an item?
Without knowing more, it's hard to say.
But basically, you can bind some value trough a ValueConverter to the UIElement.Visibility property if what you want is to hide/show any UiElement.

Resources