How to further optimize Windows Store apps? - c#

I have 2 levels deep collection that I render into something like a Header, Child Item.
Roughly, my code looks something like this:
<ScrollViewer>
<ItemsControl IsEnabled="{Binding Path=IsEnabled}"
ItemsSource="{Binding Path=HeaderViewModels, Mode=OneTime}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemsTemplate>
<DataTemplate>
<StackPanel Visibility="{Binding Path=ShouldShow, Converter={StaticResource SomeConverter}}">
<TextBlock Text="{Binding Path=Description, Mode=OneTime}" />
<ItemsControl ItemsPanel="{StaticResource WinRTXAMLWrapPanel}"
ItemsSource="{Binding Path=ChildViewModels, Mode=OneTime}">
<i:Interaction.Behaviors>
<SomeClass:AdjustSizeBehavior SizeFromParentMode="Height" />
</i:Interaction.Behaviors>
<ItemsControl.ItemsTemplate>
<DataTemplate>
<ContentControl>
<i:Interaction.Behaviors>
<SomeClass:IsEnabledBehavior />
<SomeClass:PointerPressBehavior />
<SomeClass:PointerLeaveBehavior />
</i:Interaction.Behaviors>
<StackPanel>
<TextBlock Text="X">
<i:Interaction.Behaviors>
<SomeClass:SetXMarkColor />
</i:Interaction.Behaviors>
</TextBlock>
<TextBlock Text="{Binding Path=Description, Mode=OneTime}" />
</StackPanel>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
</ScrollViewer>
Left out the styling, but its pretty much background, margins, font-size, etc. Also, you can see I'm using lots of Bindings and Behaviors.
I already did most of the optimization I can think of. Removed unnecessary UI elements (ex. rectangles used for 'backgrounds'), used StackPanel instead of Grid, set column / height to static instead of auto. Basically done what I can on this links: Twelve ways to improve wpf performance and Best practices for Windows Store Apps
With the optimizations I have done, I have actually reduced loading time of 10 headers + 8 child each (total of 80), from 1.8 sec to around 0.5 ms - 0.6 ms.
However, I would like it to reach less than 0.5 ms so it is like 'instant'.
Is there anything else I can do to improve performance?
Thank you!

It looks like your XAML is quite clean. What about your C# code?
If you use async/await, and push tasks into a background thread, it can really boost performance. Async/await is the secret to creating fast, ressponsive apps.
Visual Studio 2015 has some great improvements when it comes to identifying and fixing WPF performance bottlenecks.
You can identify which lines of code are taking the longest, and are thus a candidate for pushing onto a background thread using async/await, using the profiler. The profiler is awesome: it displays how long each block or line of code has taken, in milliseconds, right in the editor.
More:
https://channel9.msdn.com/Events/Build/2015/3-635
https://channel9.msdn.com/Events/dotnetConf/2015/Debugging-Performance-Issues-Using-Visual-Studio-2015
While we are at it, if Microsoft implements compile time bindings in WPF, it will dramatically boost performance. Binding speed can be as much as 10x faster as its no longer based on reflection. Add your vote to implement this feature here: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/7810488-implement-x-bind-for-wpf

The question of whether or not to use to use a master/detail grid is an interesting related question. I was chatting to a dev who has been using WPF since it was released in 2006. He is a bit of a guru, and he was of the opinion that master/detail grids are not always the best thing from both a usability and speed point of view. The reason is that you almost always end up loading all of the details on startup, which is slow, unless you resort to some interesting tricks to lazy load in the background. And if you have a few of the detail grids expanded, the screen begins to look messy.
Its almost as if master/detail grids are possible, but they are not a generally a good idea. Look around for successful, usable software that uses master/detail grids. They are relatively rare on the evolutionary landscape, with the exception of Windows Explorer style interfaces. They are not very common in Apple land, which is a hint that they are perhaps not optimum from a users point of view.
And the really odd thing is that relatively experienced programmers tend to like master/detail grids - a lot. They seem to have an intuitive appeal to programmers because they model the data so well. But from a users point of view, they would rather have a flat grid that loads up quickly, and a Properties panel below the grid which always displays details of the current row we have selected.
Yes, this answer doesn't address your exact question - it's too philosophical for that - but it sure as hell would solve your speed problems in one neat refactor, and potentially make your app more intuitive for your users.

Related

Why WPF XAML front end looks diffrent on other machines?

I wrote a WPF C# application and every element of front end is adjusted in margins, for example:
<TabItem x:Name="ClipboardItem" FontSize="15" FontFamily="Century Gothic" Height="60" Header="
Multi Clipboard" Background="#2a2a29" Foreground="#e7e8ea" Margin="-4,-7,-57,8">
On my computer, everything looks good and just how i wanted. Weird thing is about other PCs. For example on other PC2 element let's call it A looks diffrent and run over but on other PC3 element A looks exactly like on my PC but other element B looks totally diffrent. To the point, on other PCs some elements are just like they should be, but some elements are not. It's window application with rigidly set height and length. Could you tell me how to fix that?
First of all. computers can come in many different resolutions and aspect ratios. so if you want to fit them all. use GridView or a ViewBox (there's more but these are good for starters). and it's not recommended to use margins for most elements unless it's small and in a corner then again don't use that.
use something suitable instead of HorizontalAlignment="Stretch"
<GridView HorizontalAlignment="Stretch" >
<TabItem x:Name="ClipboardItem" FontSize="15" FontFamily="Century Gothic"
Height="60" Header=" Multi Clipboard" Background="#2a2a29"
Foreground="#e7e8ea">
</GridView>
Learn about Grid Views before you try this code https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/gridview-overview?view=netframeworkdesktop-4.8
if you want to maintain the aspect ratio Use View Box:
https://stackoverflow.com/a/290229/10518289
One other thing to keep in mind that all computers you test on must run the same version of .Net Framwork or the latest.

Improve performance in WPF with many UIElements

I'm very new in WPF and I need some advise on how to create a view with many UIElements at the same time. What i want to do, is to view some kind of table with fixed width and height for each cell. In each cell could be a random number of textblocks with a different back and forecolor (see image).
Image for table-like view with many UiElements
That is what I have done so far... I created an usercontrol for the content of one cell which binds the items in an itemcontrol.
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Backcolor, Converter={StaticResource IntegerToBrushConverter}}" >
<Viewbox MaxHeight="20" >
<TextBlock TextWrapping="Wrap" Text="{Binding Caption}"
Foreground="{Binding Forecolor, Converter={StaticResource IntegerToBrushConverter}}"/>
</Viewbox>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This usercontrol is also binded to an itemcontrol for representing the x-axis of my table.
<ItemsControl ItemsSource="{Binding}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:DayView DataContext="{Binding Days}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And the same is done for the y-axis with an nice scrollviewer around. So, the problem is, that there are many many elements in the virtual tree. In my sample case there are over 60.000 elements listed in the tree. This results in a bad performance, when opening the view. The scrolling performance is quite okay, but he takes several seconds to open the view.
I've tried some things like the CacheMode and so on, but all of that doesnt effect the opening performance. Using a VirtualizingStackPanel results in bad scrolling performance. I even cant figure out what takes so long to build up the Ui. Seems that he need a lot of time to measure all UiElemtents, but Im not sure...
Are there tips to make such an UiElement rich view any faster? As I said, Im very new in WPF and that is only a performance test. We have such an Ui in Winforms, but there, the whole table was user painted. In WPF it is so easy to rebuild the Winforms design with stock content-controls that I only want to draw all for myself as a last resort.
Take a look here for a possible solution to your problem by using virtualization:
WPF Data Virtualization
Also if you want to go another way, there are commercial 3rd party WPF control libraries that handle virtualization with various degrees of success. To name a few: Xceed, Syncfusion, DevExpress and Telerik.
I even cant figure out what takes so long to build up the Ui.
Hoping you are using VS2015 (or something better), there are a few ways to get an answer to what is taking so long. Visual Studio has a live visual tree tool (Debug->Windows) where you can see the visual tree in real time and it might help you find and eliminate some of the UI elements you don't really need (like borders inside more borders, etc)
Second, you can run the Diagnostic tools (Alt+F2), choose CPU usage and that should generate a report where you can see where your program is spending the most time. Hopefully this will isolate the issue to certain methods that can be optimized afterwards.
Also, more detail about your problem would be welcome. What is the code that populates the ItemsSource do exactly?

Dynamic Panel of Buttons WPF C# Common Use

I am trying to find a best or common practice for creating a table of buttons from a database list.
For my use I am creating more of a Point of Sale type screen. Where I want the categories to load as buttons on the entry screen. The buttons would have a simple task of showing a screen of more dynamically created buttons of the actual items. Those buttons would add the items to, lets call it, a ticket.
The solutions I found were few. I am also trying to code this so others can pick it up fairly quickly. I am extremely rusty and only code once in a while. So I try to follow common ways of doing it. I had some ideas but the code becomes hard to read, mostly because of me.
I saw the below link but was not sure if a ListBox was a good container for this.
Dynamic filling WrapPanel buttons from DB, setting the event handlers
I am sure a wrappenel is what I would have to use, but do I put it in a container or use it directly. Do I put it in Xaml or code it all, for issues like spacing between buttons? I think I am overthinking it and need to skip for a little bit.
Thank you,
It sounds like you want an ItemsControl, bound to your categories, with a WrapPanel as the ItemsPanel. The Button would go in the ItemTemplate.
<ItemsControl ItemsSource="{Binding CategoriesFromDatabase}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}"
Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.AddToTicketCommand}"
CommandParameter="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here I assumed that your view model has properties "CategoriesFromDatabase" (an IEnumerable that you populate from the database), and an ICommand "AddtoTicketCommand" which takes the category as a parameter.

Calendar Programming: How can I place, create and size items that represent a task using MVVM?

I just have a conceptual question here. First of all I am programming a Windows 8.1 App using C# and XAML as well as the MVVM-Light Toolkit.
I am working on a Schedule at the moment which is backed by a calendar. The calendar should have a "DayView" which consists of a timeline on the left that goes from top to bottom. Now on the right of that timeline I want to show something similar to a rectangle as a visualization for a given task with a height that represents its duration. Every task has a starting time so the top of that rectangle should be placed next to the corresponding entry in the timeline.
Well I hope it is clear what I am trying to say here basically that should look similar to the Calendar-App coming with Windows 8. I will post a screenshot of that below that post.
Now I have tried or thought of multiple things by now that lead to more or less complicated problems. The best approach I had was creating a List a placing it on the right of that timeline. Now that List would contain a huge amount of items (maybe one for each pixel) which will be changed in size. The size then is 0 or in relation to the duration of the task depending on whether there is a one or not.
But that leads to huge problems when it comes to changing an entry or having more than one task for the same time since those items wont overlap. And I don't want to place more than one or two of those per page since the performance-issue would be overkill...
One of the issues I have is that I am using the MVVM-Concept and don't know how to be able to create new UI-Elements such as a rectangle without touching the code-behind. That is why basically the only thing I have thought about by now were lists...
I hope it is clear what I meant.
Thank you very much for your help!
FunkyPeanut
Problem solved using a Grid as the ItemsPanel of an ItemsControl:
<ItemsControl Grid.Column="2" ItemsSource="{Binding Day.ItemsList, Source={StaticResource Locator}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Width="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="{Binding Height}" Width="20" Margin="{Binding Margin}">
<Grid.Background>
<SolidColorBrush Opacity="{Binding Opacity}" Color="{Binding ColorHash, Converter={StaticResource HexToColorConverter}}"/>
</Grid.Background>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
With the following Data:
ItemsList = new ObservableCollection<object>(tmpPeriodsList.Select((x, i) => new
{
ColorHash = x.ColorHash,
Index = i,
Margin = StartPosition(i),
Opacity = 0.6,
Height = 45,
}));

Best practices for designing a simple element to be used in many places, WPF

What are the best practices for designing a simple component, for example a border with a background, rounded corners and a textblock with specific styling inside? What I need to be able to do is add this component on many different objects (basically a styled label for the items). The easiest way to design such a thing, in my opinion, is via XAML, but how do I create more of these objects from the code behind?
Another option would of course to just write it all in code, but it is much slower to design the look by just looking at code. I tried googling around a bit but I suppose I am simply not figuring out the correct keywords because I was unable to find anything of use.
I think there are multiple ways of doing this. Depends on what exactly you want to achieve. You would want to read up on the following in WPF
1. UserControls
2. CustomControls
3. Styles
4. Templates
5. Resources
You could use a ContentControl and set its template. Your template would be the border/background/rounded corners etc...
<DataTemplate x:Key="MyTemplate">
<Border>
...
<TextBlock Text="{TemplateBinding Content}" />
...
</Border>
</DataTemplate >
You'd use it like this:
<ContentControl ContentTemplate="{StaticResource MyTemplate}" Content="blah blah" />

Categories

Resources