Silverlight 3 Checkbox Listbox bug when scrolling? - silverlight

I've spent a few minutes searching on Google and have not found anything related to this issue I'm having:
Today I upgraded to the Silverlight 3 SDK and converted a project that I'm working on. I then noticed a bug in my program with a Listbox that has a Checkbox as its DataTemplate.
When one or more items is checked, and I scroll up and down, it seems that a few of the Checkboxes at the extremes get checked off and on randomly. This does not trigger the Checked/Unchecked event, however.
Has anyone seen this behavior? I'm not doing anything out of the ordinary, simply scrolling up and down once at least one checkbox has been checked, and a couple of others that I have not touched seem to get checked on and off repeatedly. This was definitely not happening with the Silverlight 2 SDK.
Here's the XAML definition for my Listbox:
<ListBox x:Name="cBoxSalesmen" Width="135" Height="200"
HorizontalAlignment="Left" VerticalAlignment="Top">
<ListBox.Template>
<ControlTemplate>
<Border Style="{StaticResource BorderStyleThin}">
<StackPanel Orientation="Vertical">
<TextBlock Text="Salesmen" />
<ScrollViewer Height="176" VerticalScrollBarVisibility="Visible" >
<ItemsPresenter />
</ScrollViewer>
</StackPanel>
</Border>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Margin="0" Content="{Binding}" FontSize="10" HorizontalAlignment="Left"
Checked="SalesmenCheckbox_Checked" Unchecked="SalesmenCheckbox_Unchecked"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

The default ItemsPanel of the ListBox is the VirtualizingStackPanel. You can change it to use the StackPanel, this way you problem is solved.
Use this code:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
<ListBox.ItemsPanel>

I suspect your problem is a result of ListBox (in SL3) now using an ItemCollectionGenerator. The concept behind this is that not all the objects found in the source data collection need to have had their corresponding instance of the DataTemplate created and added to the Visual Tree. As you scroll toward the bottom items that may soon be needed are created. Additionally items that have already be created but are now scrolled quite same way out of view can be removed. If the user scrolls up they are re-created.
If this is the case then the IsChecked state of any checkbox in this list will be lost at some point for large lists. To solve this you would need include a property in the data type to which you can bind IsChecked. Hence as ListBox re-creates items it correctly assigns the IsChecked value.

Related

WPF TextBox in DataTemplate of ToggleButton does not show text if in toolbar flyout

If I put the Column where the toolbar is hosted to be very big (800) then all the text is visible:
but if I put a smaller column this happens:
But I cannot understand why:
<DataTemplate x:Key="IconFilterButton">
<StackPanel Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Style="{StaticResource LargeIconStyle}"
Text="{Binding}" />
<TextBlock
Margin="6,0,0,0"
VerticalAlignment="Center"
DataContext="{Binding}"
Style="{StaticResource BodyTextStyle}"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ToggleButton}, Path=Tag}" />
</StackPanel>
</DataTemplate>
and here the definition
<ToggleButton
x:Name="DFilter"
Click="Filtering_Click"
Content=""
ContentTemplate="{StaticResource IconFilterButton}"
Tag="1d"
/>
<ToggleButton
x:Name="WFilter"
Click="Filtering_Click"
Content=""
ContentTemplate="{StaticResource IconFilterButton}"
Tag="1w"
/>
Even worst if I click on the button once they are out:
and then the text is visible but is wrong as the TextBlock is not considered in the object size:
The WPF ToolBar control uses a custom panel for the overflow Popup. In many styles, the ToolBarOverFlowPanel has a property WrapWidth set to a static value like 200. This determines how many items can be displayed before it wraps to another row in the popup.
I've created custom styling for this control and have found that the ToolBarOverFlowPanel used internally is buggy. That's probably the source of your problem.
You can re-template the ToolBar and wire-up a different value for WrapWidth to try to fix the issue, but my guess is that you'll still run into layout problems.
Otherwise, you might consider making your own replacement control.

Move a popup after databinding

I would like to display a popup above my control when the user 'mouse over', problem is that the contents of the popup is a ListBox that databinds so I do not know the size of the control (to set the margins), I have tried every event listed in intellisense on the popup but the ActualHeight of the popup is zero (want to subtract from Margin.Top), any ideas?
For this, I would recommend using a ToolTip. This way you can format the tool tip to show with a list box that is data bound. For example: A normal tooltip would look like:
<sdk:Label Content="{Binding SomeBinding}" Width="Auto" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ToolTipService.ToolTip>
<ToolTip Content="Some tool tip." Name="ttSomeToolTip"></ToolTip>
</ToolTipService.ToolTip>
</sdk:Label>
What I assume you're doing is this:
<sdk:Label Content="{Binding SomeToolTip}" Width="Auto" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ToolTipService.ToolTip>
<ToolTip Name="ttSomeToolTip">
<ListBox ItemsSource="{Binding MyListBoxSource}" SelectedItem="{Binding MySelectedListBoxItem,Mode=TwoWay}">
</ListBox>
</ToolTip>
</ToolTipService.ToolTip>
</sdk:Label>
I can't guarantee that this proposed solution will work, but you have one of two options: Target the LayoutUpdated event for the ToolTip and do a render transform matrix to resize the tool tip container. Theoretically, the tool tip should resize automatically. So if you're not already using the above mentioned approach, try that and see what happens.
You must run code via Dispatcher, then your code runs in UI thread and you have access to control size.
See here

Silverlight ListBox custom keyboard selection behavior

I am customizing a templated multi-selection-enabled ListBox and can't easily implement the following feature - if there is only one item selected which is also current (focused), when user navigates up or down the list the selection should follow current item. I tried to subscribe to GotFocus event of the DataTemplate's StackPanel, but apparently I don't receive those events (even though MouseEnter/MouseLeave work).
I guess I could do it by modifying a somewhat similar behavior, but isn't there an easier way? This looks like a pretty basic behavior to me...
<ListBox>
<ListBox Name="lbItems" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
MouseEnter="UIElement_OnMouseEnter"
MouseLeave="UIElement_OnMouseLeave"
GotFocus="UIElement_OnGotFocus">
<Rectangle Width="15" Height="15" Fill="{Binding Path=Brush}" />
<TextBlock Text="{Binding Path=Category}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Why might a silverlight ListBox on Windows Phone not allow me scroll all the way down to the bottom?

I have a ListBox in a grid that gets databound when the page loads... pretty straightforward. The problem I'm having is that, after the box is databound, I can scroll... but not all the way to the bottom of the list. It stops an item or two short and won't let me scroll anymore. Here's the listbox XAML:
<Grid x:Name="ContentGrid" Grid.Row="2">
<ListBox x:Name="lbFeed" ItemsSource="{Binding Items}" SelectionChanged="lbFeed_SelectionChanged" VerticalAlignment="Top" Width="480">
<ListBox.ItemTemplate>
<DataTemplate x:Key="MyDataTemplate">
<StackPanel Orientation="Vertical" Width="430">
<TextBlock Text="Some text" TextAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I can post more code, but I'm still getting my feet wet in XAML and I'm not sure what might be causing this. If you need more context, let me know and I'll add it here.
This is a known issue at this stage of ctp release if you happen to have rows that are not fixed height. If this is the case you will likely notice your scrolling is a bit jittery too. Fix the height of your content for now if this is the case for your app and all is resolved.

WPF UI persistence in TabControl

I am having issues with something that seems like it should be very simple but in fact has proven quite difficult.
Lets say you have a TabControl bound to an itemsource of ViewModels and the items displayed using a DataTemplate. Now lets say the DataTemplate consists of a Grid with two columns and a Grid splitter to resize the columns.
The problem is if you resize the columns on one tab, and switch to another tab, the columns are also resized. This is because the TabControl shares the DataTemplate among all tabs. This lack of UI persistence is applied to all elements of the template which can make for a frustrating experience when various UI components are adjusted. Another example is the scroll position in a DataGrid (on a tab). A DataGrid with few items will be scrolled out of view (only one row visible) if a DataGrid with more rows was scrolled to the bottom on another tab. On top of this, if the TabControl has various items defined in multiple DataTemplates the view is reset when you switch between items of differenet types. I can understand that this approach saves resources but the resultant functionality seems quite contradictory to expected UI behavior.
And so i'm wondering if there is a solution/workaround to this as i'm sure it's something that others have encountered before. I've noticed a few similar questions on other forums but there was no real solution. One about using the AdornerDecorator but that doesn't seem to work when used with a DataTemplate. I'm not keen on binding all the UI properties (like column width, scroll position) to my ViewModels and in fact I tried it for the simple GridSplitter example and I didn't manage to make it work. The width of the ColumnDefinitions were not necessarily affected by a grid splitter. Regardless, it would be nice if there were a general solution to this. Any thoughts?
If I ditch the TabControl and use an ItemsControl will I encounter a similar issue? Would it be possible to modify the TabControl Style so it doesn't share the ContentPresenter between tabs?
I've been messing with this on and off for a quite a while now. Finally, instead of trying to fix/modify the TabControl I simply recreated it's functionality. It's actually worked out really well. I made a Tab'like'Control out of a Listbox (Tab headers) and an ItemsControl. The key thing was to set the ItemsPanelTemplate of the ItemsControl to a Grid. A bit of Styling, and a DataTrigger to manage the Visibility of the Items and voila. It works perfect, each "Tab" is a unique object and preserves all it's UI states like scroll position, selections, column widths, etc. Any downsides or problems that might occur with this type of solution?
<DockPanel>
<ListBox
DockPanel.Dock="Top"
ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedTab}"
ItemContainerStyle="{StaticResource ImitateTabControlStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel
Margin="2,2,2,0"
Orientation="Horizontal" >
<TextBlock
Margin="4,0" FontWeight="Bold"
Padding="2"
VerticalAlignment="Center" HorizontalAlignment="Left"
Text="{Binding Name}" >
</TextBlock>
<Button
Margin="4,0"
Command="{Binding CloseCommand}">
<Image Source="/TERM;component/Images/Symbol-Delete.png" MaxHeight="20"/>
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ItemsControl
ItemsSource="{Binding Tabs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl
Content="{Binding}">
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsSelected}" Value="False">
<Setter Property="ContentControl.Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>

Resources