WPF ListBox Show WAIT Cursor? - wpf

I have a WPF ListBox that displays images loaded from a local folder,
usually somewhere between 1- 300).
I'm using a converter in my imageTemplate to make sure and show thumbnails of the images,
and not the images in their full size. Even while doing this, it still
can take several seconds to load initially.
My question is, how do I know in my ListBox when the loading of ListBoxItems
Begins/Ends, so that I can set the Mouse Cursor to a waiting status? I'm looking
for a way to notify that user that something is happening..
Here is what my ListBox looks like in XAML:
<ListBox SelectionMode="Extended"
ItemsSource="{Binding Path=ImageFiles}"
ItemTemplate="{StaticResource imageTemplate}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.IsDeferredScrollingEnabled="False"
VirtualizingStackPanel.VirtualizationMode="Recycling"
x:Name="images">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Thanks!

I answered a similar question, here.
If you don't want to do a pop-up, you could also do something similar by attaching a translucent rectangle (or some other filling control), with a message/animation in front of it, to the listbox or its parent control that gets closed asynchronously like the popup in the linked answer does. I did something like that for Silverlight back before the BusyIndicator was available, and it worked quite well. I set it up as a user control with a property for the control it should cover, so it was easily re-used.

Related

Silverlight set ListBoxDragDropTarget children/items from code behind

I have an app which builds up list boxes programmatically from the code behind.
I would like to make the elements contained in the list boxes draggable.
I know this can be achieved in the xaml by the use of a ListBoxDragDropTarget by using the following xaml code :
<toolkit:ListBoxDragDropTarget mswindows:DragDrop.AllowDrop="True">
<ListBox Width="200" Height="500" x:Name="FromBox" DisplayMemberPath="FullName">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</toolkit:ListBoxDragDropTarget>
However i need to achieve this from the code behind rather than through xaml. Is there a way of setting the drag drop target from the code behind?
I cant seem to find a property which will allow the dragDropTarget to be set. Something like:
Dim target As New ListBoxDragDropTarget
target.children.add(listbox) / target.items
Not sure if it's possible.
Thanks in advance!
Sorted the problem in the end.
I ended up setting the ListBoxDragDropTarget.content to the list box. (Which contained multiple objects)
target.Content = listBox
I then added the target to the wrapPanel, then finally added the wrapPanel to my main grid.
wp.Children.Add(target)
grdApps.Children.Add(wp)
The drag / drop functionality is now working!

Creating a static view in WPF that won't get initialized every time

I'm working on a WPF application that contains a wrapper UI that is actually the MainWindow.xaml and the content in it (ContentPresenter) gets changed each time the user chooses to move to a different section of the application.
When the user returns to the main content, I want the application not to initialize it each time, but to preserve it in the memory somehow and restore it when the user clicks on the "Home" button.
In its current state, the Home view gets initialized over and over again when moving back to the "Home" section, which causes the application to be kinda slow. My question is this: Is there a way to preserve that user control in the memory somehow so that I would be able to restore it fast?
Thanks!
Hiding is an option ofcourse as #Matt suggested. An other way is to explorer the wonderfull world of frameworks (Prism, Caliburn, Caliburn.Micro, ... )
Those deliver a great assistance in managing WPF applications.
In essence you need to keep a reference to the ViewModel, a collection in the mainviewmodel or mainview that keeps track of the loaded viewmodels.
Eventually I decided to move the ContentControl into an ItemsControl and then just hide all content controls except for the active one.
Here's a snippet of my code:
<ItemsControl ItemsSource="{Binding ViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Visibility="{Binding Visibility}" Content="{Binding ViewModel}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In my ViewModel I have the actual content and another Visibility property that is set to false when the content is not the current one and true if it is.
Thanks to all helpers!

WPF ComboBox performance problems by binding a large collections

I'm trying to bind a large collection to a ComboBox and I faced performance problems when opening ComboBox's popup. I searched internet and found that using VirtualizingStackPanel as a items panel template might help, but it helped only partially. If I bind a large collection to a ComboBox, I could open popup very quickly, that's ok, but if after that I bind another collection to a ComboBox and try to open popup again, it becomes very slow. Same is happening if you open popup for an empty ComboBox, then bind large collection and try to open popup again - it takes some seconds before popup opens.
Here is the XAML:
<ComboBox Name="cbBlah">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
and the sample code for binding to reproduce the problem:
var list = new List<string>();
for (var i = 0; i < new Random().Next(9000, 10000); i++)
list.Add(i.ToString());
cbBlah.ItemsSource = list;
I tried to make virtualizing stack panel to look like this:
<VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" />
but it doesn't help, seems VirtualizationMode is ignored so popup opens very fast only first time and then, each time after binding changes, it's very slow.
UPDATE: I thought about not binding new collection every time, but bind an ObservableCollection once and then just changing its content. Same thing, as soon as content of collection changes, opening a popup still takes several seconds :(
According to this blog: http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx
I've tested it with this code:
<ComboBox Name="cbBlah" ItemsSource="{Binding}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
It works fine for first time and next times. It's not necessary to code these lines:
<VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" />
I had the issue with slow performance as well. But I had created a class that inherited form Combobox, therefor I would like to do this programmatically. So here is that solution for other googlers out there.
ItemsPanel = new ItemsPanelTemplate();
var stackPanelTemplate = new FrameworkElementFactory(typeof (VirtualizingStackPanel));
ItemsPanel.VisualTree = stackPanelTemplate;
I just ran into this issue as well. I'm using this code in a custom combo box with a style template. When I ran my code in VS debugging mode the virtualization did not work properly. Once I ran it outside of debugging I can switch the content of the ObservableCollection without locking the UI up. It also might help if you set a max height and max width.
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/>
<Popup>
<Border/>
<ScrollViewer>
<VirtualizingStackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Grid>
</Popup>
From a usability perspective, using a standard combobox with more items than will fit on the screen is always cumbersome. It requires at least a textbox filter. In many cases the options can be prefiltered (e.g. by department, by first letter or range) that creates less objects and usualy is more user friendly.

WP7 -- Context Menu Forces Black Background for Listbox

This is probably an easy one... I have a Listbox with a ContextMenu embedded in it, and every time the ContextMenu appears, the Listbox changes its background to opaque black. How do I prevent this from happening?
Here is some sample XAML:
<ListBox x:Name="FolderItems" ItemTemplate="{StaticResource ItemTemplate}" ItemContainerStyle="{StaticResource ItemListBox}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ItemsSource="{Binding FolderItems}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu
x:Name="FolderContextMenu"
Margin="20"
Background="WhiteSmoke"
BorderBrush="Black"
BorderThickness="1.0"
Closed="ContextMenu_Closed">
<toolkit:MenuItem Loaded="ContextMenuItem_Loaded"
Opacity="0.0" Margin="5" Background="Transparent"
Click="ContextMenuItem_Click" Name="ContextMenuDelete">
<toolkit:MenuItem.Header>
<TextBlock Text="delete" FontFamily="Segoe WP Bold"/>
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</ListBox>
Thanks
Update
I still haven't figured out why the entire listbox goes black when the context menu appears. I've set everything I can think of to a transparent brush.
I fixed this for my situation by opening up the toolkit (downloading the source: Silverlight Toolkit), and editing the color values myself in ContextMenu.cs . Then, I rebuilt and targeted the dll that I created rather than the one from the installer.
The only issue is that I will now need to do this application specific, but at least I can have a resolution. I believe also that if you set IsZoomEnabled=false, it won't have this behavior in the first place, but it's a different experience.
Here's my edited version: Pastebin
Check out the lines like this, they're the ones you'll need to change:
// Create a layer for the element's background
UIElement elementBackground = new Rectangle
{
Width = ownerElement.ActualWidth,
Height = ownerElement.ActualHeight,
Fill = new SolidColorBrush(Colors.White),
};
Good luck!
There's a simple way to do this. For some reason MS Access complements the colors when using a list box. If you set the foreground to red, it will show green, etc.
So, set the background color to black (0) and the foreground color to white (16777215). Counter-intuitive but it works is MS Access 2002.
Without seeing the template you're using I can't say for sure but you've probably hardcoded a background value but not considered the different states of the list items and the default state colour/value is being displayed

Bing Maps in a Listbox boundary issue

Normally the silverlight controls know where they are in terms of who is in front of or behind. An example is putting an image inside a listbox and when you scroll up and down in the listbox, the image will disappear/hide inside the listbox boundaries.
I have put a bing map object(the one that comes with the windows phone 7 sdk) inside a listbox. When I scroll to where the map is in the listbox, it is acting like I have some flag set to "Always on Top". I can't seem to find a property that is setting this or if it's inherent in the way the maps are designed.
I haven't tried this yet, but I'm curious if I add layers with pushpins in them if they too would act "Always on Top". I've included an image to explain. As you can see below, the map is outside of the listbox's bounding area and is even overlapping a button outside of the listbox.
Link to Map Image
<ListBox Height="590">
<TextBlock IsHitTestVisible="False" Foreground="#F80046" Style="{StaticResource PhoneTextExtraLargeStyle}" TextAlignment="Center" Text="Map"></TextBlock>
<my:Map Width="445" x:Name="EventMap" Margin="0,0,0,20" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed">
<my:Map.CredentialsProvider>
<my:ApplicationIdCredentialsProvider ApplicationId="OMITED"></my:ApplicationIdCredentialsProvider>
</my:Map.CredentialsProvider>
</my:Map>
</ListBox>
I'm not sure what you're trying to accomplish, but this seems like more of a usage of ScrollViewer
<ScrollViewer>
<StackPanel>
<my:Map>
</StackPanel>
</ScrollViewer>
rather than ListBox. But anyway, I couldn't reproduce the problem. Does that button have some custom margins that could be doing that?
Here's the solution file I created to see the problem you have in the image. Note that I wasn't able to reproduce it in the solution.
http://dl.dropbox.com/u/129101/WindowsPhoneApplication1.zip

Resources