WPF pre-render a list w/o actually showing it - wpf

Is there a way to "pre-render" a list in WPF without actually showing it to the user? I have a list that renders fairly slowly ( a few seconds ) the first time it is displayed to the user.
I'd like to pre-render/pre-draw the list so that the few seconds it takes to display the list to the users is not noticeable. I'd like this to happen while the app is starting up - while my splash screen is displayed.
What is the best way to accomplish this?
EDIT:
Here is my list item style. As you can see the target type is a Button. The button also has a RoutedEvent (Command) set on it.
<Style x:Key="Button_ProductFinder_Item" TargetType="Button">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="690" Height="181" >
<Image Name="Up" Source="{StaticResource Img_ProductFinder_FriendUp}" Stretch="Uniform"/>
<Image Name="Down" Source="{StaticResource Img_ProductFinder_FriendDn}" Visibility="Hidden" Stretch="Uniform"/>
<Canvas Name="Clip" ClipToBounds="True" Height="162" Width="175" HorizontalAlignment="Left" Margin="0,10,0,0" >
<Image Name="DynamicFriend" Stretch="UniformToFill" Canvas.Left="16" Canvas.Top="-10" HorizontalAlignment="Left" Source="{Binding ImageSource}" Height="162" Width="162" />
<Canvas.RenderTransform>
<TransformGroup>
<TranslateTransform />
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
<TextBlock Name="DynamicName" Margin="210,69,0,0" Style="{StaticResource ButtonFriend_Textstyle}"
TextWrapping="Wrap" HorizontalAlignment="Left" Width="440" VerticalAlignment="Stretch" Height="Auto"
Text="{Binding ProductName}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Up" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Down" Property="Visibility" Value="Visible"/>
<Setter TargetName="Clip" Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<TranslateTransform Y="2"/>
</TransformGroup>
</Setter.Value>
</Setter>
<Setter TargetName="DynamicName" Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<TranslateTransform Y="2"/>
</TransformGroup>
</Setter.Value>
</Setter>
<Setter TargetName="DynamicName" Property="Foreground" Value="#FFFFFF"/>
<Trigger.EnterActions>
<ctrls:ButtonSoundPlayerAction SoundFile="buttonclick.wav"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Check WHAT is slow. Really. Itf it is like the db filling up the list, your question is totally off (as the perforamnce is not WPF realted).
How large is the list? I have a list of 5000 elements rendering in a moments notice. Mosty because my 4.0 virtual list only renders what is on the list. You are not data bound while fillng up the list, or?
Finally, what is slow in the rndering? Use a wpf profiler to find out and tell us - because at the nd of the day you may simply try to optimize the wrong thing.

You could always set the list (or the whole window the list is contained in) to collapsed in it's initial state, and then un-collapse it when you get word back from your data retrieval thread that it is done.
I have done that with a couple of my other programs and it works pretty well.
User executes the program, splash screen displays, and main window loads collapsed.
Data retrieval thread executes, gets data, reports it is finished.
Splash screen disappears, main window displays and list is populated.

Related

Silverlight 3 Toolkit Chart Not all Columns show

I can't seem to find the solution to this strange problem. I have a Silverlight 3 toolkit Column chart that doesn't show all the columns. I have a data set of 10 columns and it only shows 7.
image of the graph:
<UserControl x:Class="graph.bd"
xmlns:DV="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:DVC="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit">
<UserControl.Resources>
<Style x:Key="ColorByGradeColumn" TargetType="DVC:ColumnDataPoint">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DVC:ColumnDataPoint">
<Border Background="{Binding ColColor}"
BorderBrush="{Binding ColColor}"
BorderThickness="0.5">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<!-- canvases and other code goes here... -->
<DVC:Chart x:Name="Graphic" Width="350" Height="250" Background="Transparent">
<DVC:Chart.Series>
<DVC:ColumnSeries Title="Fras"
IndependentValueBinding="{Binding ColName}"
DependentValueBinding="{Binding ColValue}"
DataPointStyle="{StaticResource ColorByGradeColumn}"
>
<DVC:ColumnSeries.IndependentAxis>
<DVC:CategoryAxis Orientation="X">
<DVC:CategoryAxis.AxisLabelStyle>
<Style TargetType="DVC:AxisLabel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DVC:AxisLabel">
<Grid Width="70" ShowGridLines="True" Height="8" Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom">
<TextBlock x:Name="YAxisTitle" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}" RenderTransformOrigin="0.5,0.5" FontSize="8">
<TextBlock.RenderTransform>
<RotateTransform Angle="270" CenterX="5"/>
</TextBlock.RenderTransform>
</TextBlock>
<Grid.RenderTransform>
<RotateTransform Angle="60" ></RotateTransform>
</Grid.RenderTransform>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DVC:CategoryAxis.AxisLabelStyle>
</DVC:CategoryAxis>
</DVC:ColumnSeries.IndependentAxis>
</DVC:ColumnSeries>
</DVC:Chart.Series>
<DVC:Chart.PlotAreaStyle>
<Style TargetType="Grid">
<Setter Property="Background" Value="Black" />
</Style>
</DVC:Chart.PlotAreaStyle>
<DVC:Chart.LegendStyle>
<Style TargetType="DV:Legend">
<Setter Property="Width" Value="0"/>
<Setter Property="Height" Value="0"/>
</Style>
</DVC:Chart.LegendStyle>
<DVC:Chart.Foreground>
<SolidColorBrush Color="White"></SolidColorBrush>
</DVC:Chart.Foreground>
</DVC:Chart>
My data set is made of just 3 values: the main number which is an integer and is how high the column is, and a name for the columns which is a string and I can't show in the picture, as well as a color for the columns which binds on the style and can change on the code behind.
I also can't upgrade to silverlight 4 or higher because this page with the columns is embebed in another page which runs only on silverlight 3
EDIT: I actually have another 3 graphs in the page which work without problems, only this one is having issues. all four have the exact same code in the .xaml (obviously with different x:name) and all 4 have very similar code in the xaml.cs. Please someone help, I really need to get this issue fixed. I can provide more code if needed.
EDIT2:
I think what is happening is one of the columns is getting behind or on top of the others, but I don't understand why. None of the other graphs has this issue.
Okay, so I found out what was wrong. It turns out it was the data, one of the 10 rows that are loaded had the same value on the column that is the X axis but diffent Y value, so the chart was displaying both columns as one.
I am quite embarrassed, but I hope this will help someone out one day.

Change Background color to a Visual pattern based

I have a list of elements (simple buttons with plain textblock) which are color coded based on the list item content. User can update the Listitem and thus listitem color should change. For certain listitem background colors like "Red", I want to add a pattern as well.
I have added the following VisualPatterns in XAML:
<Window.Resources>
<VisualBrush x:Key="FwdPattern" TileMode="Tile" Viewport="0,0,15,15" ViewportUnits="Absolute" Viewbox="0,0,15,15" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Grid>
<Path Data="M 0 15 L 15 0" Stroke="Gray" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
<VisualBrush x:Key="BckPattern" TileMode="Tile" Viewport="0,0,15,15" ViewportUnits="Absolute" Viewbox="0,0,15,15" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Grid>
<Path Data="M 0 0 L 15 15" Stroke="Gray" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Window.Resources>
Button template used in ListItem is:
<Border Background="{Binding BackgroundClr}">
<Button Name="MyButton" Content="Testing">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{Binding BackgroundClr}"/>
<Style.Triggers>
<!-- This does not work, see [http://stackoverflow.com/questions/39583263/brush-mvvm-binding-does-not-give-named-color/39583422#39583422][1] -->
<DataTrigger Binding="{Binding BackgroundClr}" Value="Red">
<Setter Property="Background" Value="{StaticResource BckPattern}"/>
</DataTrigger>
<!-- This does not work either, it goes in infinite loop
and StackOverflow exception is thrown-
probably because I am reading the background color in
the datatrigger and again updating it- but i dont know-->
<DataTrigger Binding="{Binding Background.Color, RelativeSource={RelativeSource Self}}" Value="Red">
<Setter Property="Background" Value="{StaticResource BckPattern}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Border>
Currently I have no other knowledge except the Button BackgroundClr from VM to determine if I need to provide a pattern or not.
Tried Solutions
One solution is to have a bound property- PatternName and based on it, determine which pattern to apply:
The above code works, but I have to have an additional property in VM
The other solution is to access VisualBrush in VM and directly apply the pattern in BackgroundClr - i have not figured out how to do this yet.
Which is a better solution or there any other way to achieve the same?
Thanks,
RDV
Change {Binding BackgroundClr} to {Binding BackgroundClr.Color}.

Make ErrorTemplate in Style on ComboBox allow tooltip but not mouse click

I use telerik, but that should not mean much for this question. My application is WPF (.Net 4.5).
I have a style, that I use for all comboboxes, which has an errortemplate. The style looks like this:
<Style TargetType="{x:Type telerik:RadComboBox}" x:Key="RadComboBoxStyle" >
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Background" Value="{StaticResource InputBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource InputBorderBrush}" />
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource RadComboBoxValidationErrorTemplate}" />
</Style>
My ErrorTemplate looks like this:
<ControlTemplate TargetType="{x:Type Control}" x:Key="RadComboBoxValidationErrorTemplate">
<Grid ToolTipService.IsEnabled="True" ToolTipService.ShowOnDisabled="True"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors), Converter={StaticResource ValidationErrorsConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border BorderBrush="{StaticResource ErrorBrush}" BorderThickness="3" Panel.ZIndex="999" HorizontalAlignment="Right" Margin="0,0,10,0"
Background="Transparent" DockPanel.Dock="right" Width="16" Height="16" CornerRadius="10">
<Rectangle Fill="{StaticResource ErrorBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="3" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="315" />
</Rectangle.RenderTransform>
</Rectangle>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="{StaticResource ErrorBrush}" BorderThickness="1" />
</AdornedElementPlaceholder>
</Grid>
</ControlTemplate>
The entire thing is defined in a global ResourceDictionary.
What this code does, it to put a "forbidden sign" on top of the combobox (Panel.ZIndex="999"), just before the dropdown button (using margins). The Border and the Rectangle makes a sign much like this: Picture.
The combobox itself must be able to hold a tooltip, set locally. So the error-message cannot be shown in the tooltip of the combobox - unless I find a way to combine the two without having to resolve it locally (I want that code in my resourcedictionary).
I also do not want the "forbidden sign" to handle mouse clicks (it gobbles up the click and prevent the combobox from dropping down, if the user clicks on the "forbidden sign".
I tried setting IsHitTestVisible to false on the grid and on the border inside the ErrorTemplate, but that caused the Tooltip to never show.
I also tried setting IsEnabled to false on the same two constrols, but that would not send the mouseclick on to the combobox itself (the list in the combobox does not drop down).
Is there any way to do this directly in the combobox-style or errortemplate? I do not even mind having a code behind - but I really do not want to add code locally where the combobox-style is used.

WPF menu not shown in proper view

I am generating menu items dynamically, following is my menu
<ItemsControl x:Name="MainToolbar"
cal:RegionManager.RegionName="{x:Static inf:RegionNames.MainToolBarRegion}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Margin="0,10,841,0"
RenderTransformOrigin="-0.133,-5.917"
Height="28"
Width="35">
<ItemsControl.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ItemsControl.RenderTransform>
<Menu IsMainMenu="True"
Margin="0,0,0,0"
Height="28"
ItemsSource="{Binding Path=Menu}"
Width="400">
<Menu.Resources>
<Style x:Key="ThemeMenuItemStyle"
TargetType="MenuItem"
BasedOn="{StaticResource KV_MenuItem}">
<Setter Property="Header"
Value="{Binding Path=Text}"></Setter>
<Setter Property="Command"
Value="{Binding Path=Command}" />
<Setter Property="IsCheckable"
Value="True" />
<Setter Property="MinWidth"
Value="80" />
</Style>
</Menu.Resources>
</Menu>
</ItemsControl>
My menu items added to the menu correctly (from my another service)
The problem here is my generated view not showing properly, means i can only see a small box where rest view is clipped off. (it does not expand to its contents). how can i see my full menu shown?
In your ItemsControl declaration remove the Width declaration and possible the Margin as well. Those properties maybe restricting your view.

How to make a simple hyperlink in XAML?

All I want to do is make a little hyperlink in XAML. I've tried everything. I give up.
What is the syntax for this?
<StackPanel Width="70" HorizontalAlignment="Center">
<Hyperlink Click="buttonClose_Click" Cursor="Hand"
Foreground="#555" Width="31" Margin="0 0 0 15"
HorizontalAlignment="Right">Close</Hyperlink>
<Button Width="60" Margin="0 0 0 3">Test 1</Button>
<Button Width="60" Margin="0 0 0 3">Test 2</Button>
<Button Width="60" Margin="0 0 0 3">Test 3</Button>
<Button Width="60" Margin="0 0 0 3">Test 4</Button>
</StackPanel>
Visual Studio Team: In Visual Studio 2010 I want Clippy to pop up and say "It seems you are trying to make a hyperlink" and tell me how to do it. Can't you do that with MEF? It would be retro cool, and these little "how do I do what I already know how to do in HTML" issues burn up so much time during the learning process with XAML.
You can't add a Hyperlink to a StackPanel -- you'll get a runtime error. (Actually, I'm kinda surprised it's not a compile-time error.) That's because Hyperlink doesn't live in the "controls" side of WPF with <Button> and <StackPanel> and other things that are laid out on rectangular chunks of screen and descend from UIElement. Instead, it lives in the "text" side of things, with <Bold> and <Run> and <Paragraph> and other generally texty things that word-wrap and flow in lines and paragraphs and descend from TextElement.
Once you realize that there are two separate class hierarchies with different layout behaviors, it makes sense that Hyperlink would be on the "text" side of things (makes it easy to e.g. have a paragraph with a hyperlink in the middle, and even for that hyperlink to wrap across a line break).
But no, it's not so discoverable when you're starting out.
To mix the two worlds, and use a hyperlink as a control, all you need to do is put it in a TextBlock. TextBlock is a control-ish thing (i.e., can go in a StackPanel) that contains text-ish things (i.e., can contain a Hyperlink):
<TextBlock><Hyperlink Click="buttonClose_Click">Close</Hyperlink></TextBlock>
You can use a Button with a custom control template, the code below is a limited hyperlink style button (for example it only support textual hyperlinks) but maybe it'll point you in the right direction.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="Link" TargetType="Button">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock TextDecorations="Underline"
Text="{TemplateBinding Content}"
Background="{TemplateBinding Background}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Button Content="Click Me!" Style="{StaticResource Link}"/>
</Page>
Try this:
<TextBlock>
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
NavigateUri="http://www.msn.com">MSN</Hyperlink>
</TextBlock>
private void Hyperlink_RequestNavigate(object sender,
System.Windows.Navigation.RequestNavigateEventArgs e)
{
System.Diagnostics.Process.Start(e.Uri.AbsoluteUri);
}
<TextBlock>
<Hyperlink NavigateUri="{Binding YourUri}" RequestNavigate="YourRequestNavigate">
<TextBlock Text="{Binding YourText}" />
</Hyperlink>
</TextBlock>
This will linkify any binded text in the nested textblock, i have not found a better way yet, i would like the first textblock to not be there if possible.
This will work for DataTemplates aswell.
You may find that if you're binding to anything other than simple text values you will need to use ContentPresenter otherwise nothing will appear, this could be true if you're binding to an XML data source.
A Property Trigger for IsMouseOver gives the text an underline.
An example where I"m binding to XML is presented below.
<Style x:Key="JobNumberStyleButton" TargetType="{x:Type Button}">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock>
<ContentPresenter
Margin="0,0,0,0"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Padding="0,0,0,0" Margin="0,0,0,0">
<Underline>
<ContentPresenter
Margin="0,0,0,0"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Underline>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
You can simply use HyperlinkButton.
When it is clicked on, the URL will be displayed in your web browser:
<HyperlinkButton
NavigateUri="https://dev.windowsphone.com"
TargetName="_blank"
Content="Windows Phone Dev Center" />
Usually, the meaning of an Hyperlink is to give an anchor to send the user to another Page or generally speaking to another resource, so it's implemented in such a way and you have to specify the location for that resource like this:
<HyperLink NavigateUri="http://www.site.com">
Web Site
</HyperLink>
However, i've found this blog post with a custom TextBlock that is used as an HyperLink and supports click events.
in UWP with mvvmcross i'm using this
<HyperlinkButton Content="{Binding TextSource, ConverterParameter=MyUrl, Converter={StaticResource Language},
FallbackValue=_MyUrl}" NavigateUri="http://www.google.com" />

Resources