Why WPF XAML front end looks diffrent on other machines? - c#

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.

Related

Slider control giving odd values?

Okay so I know I can fix this with some string formatting on the textbox, but it's bugging me why this is happening in the first place. I have a slider control, which is going to get its max, min, and precision values from the viewmodel, depending on which page it's loaded into.
As an example, I've hard coded these values.
<DockPanel VerticalAlignment="Center"
Margin="40,0,0,0"
Height="100">
<TextBox Text="{Binding ElementName=Slider, Path=Value, UpdateSourceTrigger=PropertyChanged}"
DockPanel.Dock="Top"
TextAlignment="Right"
Width="634"
Margin="0,0,0,20" />
<Slider DockPanel.Dock="Bottom"
Name="Slider"
Width="634"
Padding="0"
Maximum="5000"
Minimum="-5000"
SmallChange="0.01"
LargeChange="0.01"
TickFrequency="0.01"
SnapsToDevicePixels="True"
IsSnapToTickEnabled="True" />
</DockPanel>
I know I probably don't need a few of those properties, but threw them in trying to fix this.
For the most part this has worked, and the slider is being constrained to two decimal places. But I've noticed (especially with large ranged) that I'm still getting random values which are ignoring this. For example when I set a range of -5000 to 5000 I still randomly get values like 80.20000002.
I know I can apply a string format to the textbox to resolve the issue, (although a tad annoying with the viewmodel setting the precision) just wondering why it's happening.
As an aside, users also need to be able to set the value using a keyboard, again this works perfectly, but I'm wondering if there's a way to make the slider textbox acceppt a decimal point without having a number behind it.

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?

WPF MVVM Chartplotter: Dynamically bind multiple Lines

I'm trying to make the WPF Chartplotter work with some WPF MVVM. As a target of my interest I've chosen our TeamCity Tests Performance. The current Plotter is looking like this:
<dd:ChartPlotter Grid.Row="1">
<dd:ChartPlotter.HorizontalAxis>
<dd:HorizontalIntegerAxis />
</dd:ChartPlotter.HorizontalAxis>
<dd:ChartPlotter.VerticalAxis>
<dd:VerticalIntegerAxis/>
</dd:ChartPlotter.VerticalAxis>
<dd:VerticalAxisTitle Content="Performance in Minutes" FontSize="10" />
<dd:HorizontalAxisTitle Content="Build by ID" FontSize="10" />
<dd:LineGraph DataSource="{Binding TestRunsPerformance, IsAsync=True}" Stroke="Green" StrokeThickness="2">
<dd:LineGraph.Description>
<dd:PenDescription DescriptionString="Test" />
</dd:LineGraph.Description>
</dd:LineGraph>
<dd:LineGraph DataSource="{Binding TestSlowRunsPerformance, IsAsync=True}" Stroke="Red" StrokeThickness="2">
<dd:LineGraph.Description>
<dd:PenDescription DescriptionString="TestSlow" />
</dd:LineGraph.Description>
</dd:LineGraph>
</dd:ChartPlotter>
</Grid>
So I have basically two Test-Categories and for each I show a LineGraph in the Plotter, which I bind to the EnumerableDataSource in the ViewModel. Unfortunately I couldn't test it, but I'm certain it will work this way, since one LineGraph did work so far.
This is cool, but now I would like to make a second Chart with the Unit-Tests with the highest influence. But for this, I can't just create LineGraphs in the XAML and bind, but I would need something like a LineGraph Collection and set an amount of LineGraphs dynamically. Since I'm also learning MVVM, it would be troublesome If I'd really need to do this in the Code behind.
Unfortunately, all the Examples I found so far do exactly this, for example: Dynamic Line chart in C# WPF Application
I found also examples to make this work for Canvas: Is it possible to bind a Canvas's Children property in XAML? but these are UIElements, not PlotterElements.
Is what I'm trying even possible or am I doing something fundamentally wrong?

How to further optimize Windows Store apps?

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.

ComboBox Dropdown Appears Beneath Window

So I was have a combobox like below, coded like this;
AllowsTransparency="True" Background="Transparent">
<Border CornerRadius="10" Background="Beige" BorderBrush="Aqua" BorderThickness="2">
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Label Name="lblText"></Label>
<ComboBox Name="cbxNumbers"></ComboBox>
<TextBox Name="txtNumbers" Visibility="Collapsed"></TextBox>
<Button HorizontalAlignment="Center" Name="btnDone"
Click="btnDone_Click">That's Right!</Button>
</StackPanel>
<Button VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="1"
FontSize="8" Name="btnChangeInput" Click="btnChangeInput_Click">Let me chose the number
</Button>
</Grid>
</Border>
And then populated in code like this;
lblText.Content = Text;
cbxNumbers.Items.Add(5);
cbxNumbers.Items.Add(10);
cbxNumbers.Items.Add(50);
cbxNumbers.Items.Add(100);
cbxNumbers.Items.Add(1000);
cbxNumbers.Items.Add(10000);
cbxNumbers.Items.Add(100000);
cbxNumbers.Items.Add(1000000);
cbxNumbers.SelectedIndex = 0;
My question is obviously, why is my Dropdown showing beneath my window?
UPDATE
Quote Microsoft
Thank you for reporting this issue. Though this issue is under
investigation, we will likely not have a fix available in .NET 4.0. We
will update this bug again when we are able to fix the issue in a
future release. Thanks!
Great... any ideas for a work around?
This is a well documented bug with AllowTransparency=TRUE. It only happens on some computers running Win XP.
http://connect.microsoft.com/VisualStudio/feedback/details/465964/wpf-combobox-dropdown-list-appears-behind-the-form-when-allowstransparency-true
A workaround is found here:
As noted before, this is an issue with layered windows on XP. There is
not much that can be done at the WPF level to solve this, and given
that XP is no longer being serviced this isn't very likely to be
fixed. There are potentially workarounds you can employ, though.
The source of the problem is that WPF uses something called "Layered
Windows" when WindowStyle=None and AllowsTransparency=True. Often the
reason for doing this is to implement custom window chrome. Recently
the WPF team published a library that allows you to get custom chrome
without resorting to layered windows. The library is available at
http://code.msdn.microsoft.com/WPFShell
This doesn't support per-pixel opacity, but it does allow for
completely custom rendering of the window, including areas normally
managed by the system. It lets you set the radii of the windows
corners, but not have a completely arbitrary shape. If you can use
this library instead of AllowsTransparency=True then it should solve
this issue.
Microsoft has issued a hotfix, but it seems to not have fixed all problems related to the issue.

Categories

Resources