25 WPF Calendars in one window, takes 5 seconds to open Window - c#

I'm new to WPF, and trying to get an idea of just how much slower it might be. I started a new WPF app, in Visual Studio 2010 (.NET 4), and created this XAML:
<Window x:Class="CalendarTest1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="800" Width="1000">
<WrapPanel>
<Calendar />
<Calendar />
<Calendar />
...repeats for a total of 25 calendar objects...
</WrapPanel>
</Window>
When I run my application, in the IDE or not, it takes 5 seconds for the window to open. Once open, it redraws quickly (as I resize it) and everything seems snappy.
My PC isn't the fastest: AMD Dual Core 2.3GHz, 2GB RAM, XP 32-bit OS, on-board video.
I can place 25 buttons, instead of Calendars, and that loads in less than 1 second.
I'm trying to create something like the little month calendars in the day view in the MS Outlook calendar, like this:
So I was thinking I could use a WrapPanel and add/remove Calendar controls as it resizes. I might not need 25, but even with 9 or 12 it is slower than I would think (I have a legacy Win32 app that displays 18 calendars like this in less than 1 second).
My questions are:
Is the Calendar control slow because of a certain design -- either a bad design, or just not designed for this usage, or is it just slow because it is trying to display a lot of data/controls/info?
If I go to the trouble to create my own control, assuming I use a good design (general ideas welcome), can it be a lot faster, or is this just "typical" for WPF?
Is there something I can do to make the default Calendar control faster for this usage?

Not an answer per se, but adding this to Window.Resources reduced the load time 50% in my machine (which is now under 1 second for 25 calendars)
<Window.Resources>
<Style TargetType="CalendarDayButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CalendarDayButton">
<ContentPresenter ContentSource="Content" Margin="2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Calendar">
<Setter Property="CalendarDayButtonStyle" Value="{StaticResource {x:Type CalendarDayButton}}"/>
</Style>
</Window.Resources>
Edit:
This visual change does not affect the control's functionality. All the Calendar's Day items are still Selectable, and you can bind the Calendar.SelectedDate property.
There's just no visual indication that an item is selected, therefore clicking on the days seems to do nothing.
Just add this to your ControlTemplate:
<ControlTemplate TargetType="CalendarDayButton">
<ContentPresenter ContentSource="Content" Margin="2"/>
<ControlTemplate.Triggers>
<!-- Set The FontWeight to "Bold" when Selected -->
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
You can play around with this ControlTemplate and its Triggers to add visual effects. Though keep in mind the more complex the template, the longer it will take to load.

This will give you an idea of what a calendar is versus a button using Snoop. Yes, we do expect a lot of calendars to take a lot more rendering time. If you need to use a lot of them, I'd attempt to create your own that's simpler and/or virtualize them
Heres a button, 3 children...
And heres a Calendar, 522 children. Notice each of the CalendarButtons I didn't expand still have 9 children each

I'll update this as I have time to finish up this new control, but so far I proved to myself that I can have a large number of controls in a window and still have it load quickly. In this case, 1050 TextBlocks (7 columns * 6 rows * 25 instances of my user control), and my window loads in less than 1 second.
Here is my simple user control so far:
<UserControl x:Class="FastCalendar.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FastCalendar"
xmlns:vm="clr-namespace:FastCalendar.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Margin="5">
<UserControl.Resources>
<vm:MainViewModel x:Key="ViewModel" />
</UserControl.Resources>
<ItemsControl Width="180" Height="170" ItemsSource="{Binding Path=Days, Source={StaticResource ViewModel}}">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Path=Row}" />
<Setter Property="Grid.Column" Value="{Binding Path=Column}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Path=Day}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</UserControl>
I placed 25 of those inside a WrapPanel, and it loads in less than 1 second. I still need to add more controls and styles to my user control, but I'm thinking it will still be much faster than the built-in Calendar control (I hope).
p.s.-Even with 50 copies of my user control on the window, it loads in about 1 second.

Related

How to 'Disable' a WPF UserControl?

I have a UserControl, and I need to change its appearance when 'IsEnabled' is false. I know this is pretty basic WPF styling, but I can't seem to put the pieces together. I assume that I need to create a Style, and add a trigger for "Property="IsEnabled" Value="False". But where do I put the Style definition? (<UserControl.Resources>?) How do I apply it? ... in the UserControl or in the Parent window? Does my trigger need to be inside a Setter element? Does the style need to be applied to the UserControl or to its children? I don't know what other questions I need to ask!
If you feel this is a duplicate of another question, please direct me to it.
If you know of a good, simple tutorial on WPF styling that would answer my questions, I would be very grateful to hear of it.
My code looks like this:
<UserControl x:Class="UserControls.UCDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UserControls"
mc:Ignorable="d"
d:DesignHeight="240" d:DesignWidth="200">
<UserControl.Resources>
</UserControl.Resources>
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="5*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="{Binding BG}" >
<Ellipse Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" Fill="DeepSkyBlue" />
</Grid>
<Grid Grid.Row="1" Background="Tomato" />
</Grid>
<uc:UCDemo x:Name="Demo" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="300,100,0,0" Width="80" Height="100" Style="{StaticResource uc:DemoStyle}"
Visibility="{Binding LightVisible, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource BooleanToVisibilityConverter}}" />
Thank you for your help!
It depends on how exactly the appearance should change when IsEnabled is false.
A simple Style with a Trigger could be assigned directly to the UserControl's Style property. The one below just sets the Opacity to 0.5.
<UserControl ...>
<UserControl.Style>
<Style TargetType="UserControl">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Style>
<Grid Background="Transparent">
...
</Grid>
</UserControl>
I'm not sure I get what your question is. However in order to change the IsEnabled property of a control, depending on an other controls is:
Let's suppose that the control which its IsEnabled must be changed, is A and the control which A is depends on, is B.
First, choose a name for B: x:Name = "AccessCheckBox".
Then Write a binding like this for control B:
< ... IsEnabled = {Binding ElementName = "AccessCheckBox", Path="IsChecked".../>
Done. I hope I got what you mean.

Why WPF cut components when I run the program

I'm doing a WPF program, with some textbox, labels and buttons.
Using the XAML designer, it works fine, the components are shown as they should. But when I run the program, it seems that the window shortens and cut some components in the sides.
Why are the components (button and labbel) being cut only when I run the program?
Here's the Xaml code of the 2 affected components:
<Window x:Class="XML_Edit.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XML_Edit"
mc:Ignorable="d"
Title="XML_Edit" Height="380" Width="470" ResizeMode="NoResize" Icon="Imagenes/xml.png">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
<Style TargetType="{x:Type TextBox}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<Grid Background="#FF363944">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="49*"/>
<ColumnDefinition Width="183*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="80"/>
<RowDefinition Height="80"/>
<RowDefinition Height="45"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<!-- Components -->
<Button Name="btCambiarContenido" Grid.Row="4" Content="Cambiar Contenido" VerticalAlignment="Center" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="26,80,0,16" Height="36" Width="135" Click="BtCambiarContenido_Click" TabIndex="5" Background="{x:Null}" BorderBrush="#FF4EB8CE" FontSize="14" Grid.ColumnSpan="2" Foreground="#FF4EB8CE"/>
<Label Name="lbSeleccionarRuta" Grid.Row="1" ToolTip="Seleccionar archivo" Height="32" Width="32" Margin="293.333,32,41,16" MouseDown="LbSeleccionarRuta_MouseDown" Grid.Column="1">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_azul.png"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_gris.png"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
They are shown fine in the WPF editor:
But they fet cut when I run the program:
You're setting your Button height to 36 pixels and giving it a margin of 26,80,0,16. This is effectively telling the layout manager that you want 36+80+16=132 pixels reserved to accommodate that button in row 4.
Meanwhile, in your grid layout you're specifying the rows 0-3 to have 15+80+80+45 pixels reserved. Combined with the 132 you're reserving for your button that's 352. But you're also explicitly setting your window height to 380, and that has to accommodate not just your 352 client area pixels but also the border and caption (as an experiment set your WindowStyle to None to remove the border and caption bar and you'll see your full control appear again). The layout manager has to cut pixels somewhere, and since row 4 is the only one you've specified with a "*" that's where they get cut, so the top and bottom of your button get cut as well. The reason you're not seeing this in designer is because it's using different theming to your OS, which is taking into account things like screen DPI, Windows theme settings, accessibility and several other things; the caption bar in designer is simply a bit smaller.
Issues like this are one of the many reasons you have to be careful doing explicit pixel layouts in WPF, and why you have to be especially careful with margins.

Add top margin in Grid RowDefinition [duplicate]

Is it easily possible to specify a margin and/or padding for rows or columns in a WPF Grid?
I could of course add extra columns to space things out, but this seems like a job for padding/margins (it will give much simplier XAML). Has someone derived from the standard Grid to add this functionality?
RowDefinition and ColumnDefinition are of type ContentElement, and Margin is strictly a FrameworkElement property. So to your question, "is it easily possible" the answer is a most definite no. And no, I have not seen any layout panels that demonstrate this kind of functionality.
You can add extra rows or columns as you suggested. But you can also set margins on a Grid element itself, or anything that would go inside a Grid, so that's your best workaround for now.
Use a Border control outside the cell control and define the padding for that:
<Grid>
<Grid.Resources >
<Style TargetType="Border" >
<Setter Property="Padding" Value="5,5,5,5" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Grid.Column="0">
<YourGridControls/>
</Border>
<Border Grid.Row="1" Grid.Column="0">
<YourGridControls/>
</Border>
</Grid>
Source:
Original Source
and from Way Back Machine
You could use something like this:
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Padding" Value="4" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Or if you don't need the TemplateBindings:
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Padding="4">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thought I'd add my own solution because nobody yet mentioned this. Instead of designing a UserControl based on Grid, you can target controls contained in grid with a style declaration. Takes care of adding padding/margin to all elements without having to define for each, which is cumbersome and labor-intensive.For instance, if your Grid contains nothing but TextBlocks, you can do this:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="10"/>
</Style>
Which is like the equivalent of "cell padding".
Edited:
To give margin to any control you could wrap the control with border like this
<!--...-->
<Border Padding="10">
<AnyControl>
<!--...-->
I am surprised I did not see this solution posted yet.
Coming from the web, frameworks like bootstrap will use a negative margin to pull back rows / columns.
It might be a little verbose (albeit not that bad), it does work and the elements are evenly spaced and sized.
In the example below I use a StackPanel root to demonstrate how the 3 buttons are evenly spaced using margins. You could use other elements, just change the inner x:Type from button to your element.
The idea is simple, use a grid on the outside to pull the margins of elements out of their bounds by half the amount of the inner grid (using negative margins), use the inner grid to evenly space the elements with the amount you want.
Update:
Some comment from a user said it doesn't work, here's a quick video demonstrating: https://youtu.be/rPx2OdtSOYI
<StackPanel>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<Setter Property="Margin" Value="-5 0"/>
</Style>
</Grid.Resources>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10 0"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Btn 1" />
<Button Grid.Column="1" Content="Btn 2" />
<Button Grid.Column="2" Content="Btn 3" />
</Grid>
</Grid>
<TextBlock FontWeight="Bold" Margin="0 10">
Test
</TextBlock>
</StackPanel>
You could write your own GridWithMargin class, inherited from Grid, and override the ArrangeOverride method to apply the margins
I did it right now with one of my grids.
First apply the same margin to every element inside the grid. You can do this mannualy, using styles, or whatever you like. Lets say you want an horizontal spacing of 6px and a vertical spacing of 2px. Then you add margins of "3px 1px" to every child of the grid.
Then remove the margins created around the grid (if you want to align the borders of the controls inside the grid to the same position of the grid). Do this setting a margin of "-3px -1px" to the grid. That way, other controls outside the grid will be aligned with the outtermost controls inside the grid.
I ran into this problem while developing some software recently and it occured to me to ask WHY? Why have they done this...the answer was right there in front of me. A row of data is an object, so if we maintain object orientation, then the design for a particular row should be seperated (suppose you need to re-use the row display later on in the future). So I started using databound stack panels and custom controls for most data displays. Lists have made the occasional appearance but mostly the grid has been used only for primary page organization (Header, Menu Area, Content Area, Other Areas). Your custom objects can easily manage any spacing requirements for each row within the stack panel or grid (a single grid cell can contain the entire row object. This also has the added benefit of reacting properly to changes in orientation, expand/collapses, etc.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<custom:MyRowObject Style="YourStyleHereOrGeneralSetter" Grid.Row="0" />
<custom:MyRowObject Style="YourStyleHere" Grid.Row="1" />
</Grid>
or
<StackPanel>
<custom:MyRowObject Style="YourStyleHere" Grid.Row="0" />
<custom:MyRowObject Style="YourStyleHere" Grid.Row="1" />
</StackPanel>
Your Custom controls will also inherit the DataContext if your using data binding...my personal favorite benefit of this approach.
I had similar problem recently in two column grid, I needed a margin on elements in right column only. All elements in both columns were of type TextBlock.
<Grid.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource OurLabelStyle}">
<Style.Triggers>
<Trigger Property="Grid.Column" Value="1">
<Setter Property="Margin" Value="20,0" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
One possibility would be to add fixed width rows and columns to act as the padding / margin you are looking for.
You might also consider that you are constrained by the size of your container, and that a grid will become as large as the containing element or its specified width and height. You could simply use columns and rows with no width or height set. That way they default to evenly breaking up the total space within the grid. Then it would just be a mater of centering your elements vertically and horizontally within you grid.
Another method might be to wrap all grid elements in a fixed with single row & column grid that has a fixed size and margin. That your grid contains fixed width / height boxes which contain your actual elements.
in uwp (Windows10FallCreatorsUpdate version and above)
<Grid RowSpacing="3" ColumnSpacing="3">
Though you can't add margin or padding to a Grid, you could use something like a Frame (or similar container), that you can apply it to.
That way (if you show or hide the control on a button click say), you won't need to add margin on every control that may interact with it.
Think of it as isolating the groups of controls into units, then applying style to those units.
As was stated before create a GridWithMargins class.
Here is my working code example
public class GridWithMargins : Grid
{
public Thickness RowMargin { get; set; } = new Thickness(10, 10, 10, 10);
protected override Size ArrangeOverride(Size arrangeSize)
{
var basesize = base.ArrangeOverride(arrangeSize);
foreach (UIElement child in InternalChildren)
{
var pos = GetPosition(child);
pos.X += RowMargin.Left;
pos.Y += RowMargin.Top;
var actual = child.RenderSize;
actual.Width -= (RowMargin.Left + RowMargin.Right);
actual.Height -= (RowMargin.Top + RowMargin.Bottom);
var rec = new Rect(pos, actual);
child.Arrange(rec);
}
return arrangeSize;
}
private Point GetPosition(Visual element)
{
var posTransForm = element.TransformToAncestor(this);
var areaTransForm = posTransForm.Transform(new Point(0, 0));
return areaTransForm;
}
}
Usage:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:GridWithMargins ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Fill="Red" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Rectangle Fill="Green" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Rectangle Fill="Blue" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</local:GridWithMargins>
</Grid>
</Window>
Sometimes the simple method is the best. Just pad your strings with spaces. If it is only a few textboxes etc this is by far the simplest method.
You can also simply insert blank columns/rows with a fixed size. Extremely simple and you can easily change it.

How to Change Titlebar Buttons WPF C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to do a customization with the close, minimize and maximize buttons in a window titlebar. In some programs, the titlebar is different but I don't want to change the complete titlebar, only the buttons. Can anyone help me about that?
In general, the title bar of a window belongs to the so-called non-client area of the window.
What that means is you cannot change the way the buttons look and you cannot add custom ones etc.
To do that, you need to roll your own window style or use a library that does that for you.
Some useful tutorials or starting points might be this MSDN article or this tutorial on how to create a custom window.
To create your own window style, you can use this simple style as a base:
<Style x:Key="MyCustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- this displays the window title -->
<TextBlock TextAlignment="Center"
Text="{TemplateBinding Title}"/>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<!-- the minimize button, using your own style -->
<Button Style="{StaticResource MyMinimizeButtonStyle}"
Width="20"
Height="20" />
<!-- the close button, using your own style -->
<Button Style="{StaticResource MyCloseButtonStyle}"
Width="20"
Height="20" />
</StackPanel>
<!-- this displays the actual window content -->
<ContentPresenter Grid.Row="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can customise the chrome of windows using windowchrome.
https://msdn.microsoft.com/en-us/library/system.windows.shell.windowchrome(v=vs.110).aspx
You can use that to entirely re-template your window.
Note that the class has moved since the following was written.
https://blogs.msdn.microsoft.com/wpfsdk/2010/08/25/experiments-with-windowchrome/
This can have odd side effects eg when you maximise a window in win10.
You can use WindowChrome to custom a window style:https://github.com/DinoChan/WindowDemo
This style does not use SystemParameters2 class because it is not exist in .net 4.5.

WPF - how to determine why this XAML style code is not working?

Any advice how to fault find to work out why the Grid.Resources styles in this XAML is not making any difference it seems to the end result?
Note I'm using Charting from the WPFToolkit so to adjust how a chart looks it seems one has to apply the style areas (suggested by someone on the forum).
So my question is generically, noting I'm trying to adjust the look of a 3rd party graph, how can I debug/fault-find to understand what's going wrong? Is there a debugging trick? For example when I increased the BorderThickness to 30 I couldn't see a difference. What I'm really after is the equivalent of FireBug for HTML/CSS, which lets you understand/view what CSS is being applied to what elements.
EDIT: So I really (I think) want to be able to walk the object tree of the graph, and referring back to the template changes put in the Grid.Resources area, see why they didn't occur.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" mc:Ignorable="d" x:Name="Splash" x:Class="MyInternetUsage.SplashWindow"
Title="SplashWindow" Height="421" Width="570">
<DockPanel>
<StackPanel VerticalAlignment="Top" DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="Configure" HorizontalAlignment="Left" Margin="0" Width="78" VerticalAlignment="Center" Name="ConfigureButton" Click="ConfigureButton_Click" />
<Button Content="Start" Name="StartButton" Width="78" Click="StartButton_Click" />
<Button Content="Stop" Name="StopButton" Width="78" Click="StopButton_Click" />
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Summary" Grid.Column="0"/>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<Grid Grid.Column="2">
<Grid.Resources>
<Style x:Key="GooglePolylineStyle" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="30"/>
</Style>
<Style x:Key="GoogleLineDataPointStyle" TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Background" Value="#0077CC" />
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="30"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="1">
<ToolTipService.ToolTip>
<StackPanel Margin="2,2,2,2">
<ContentControl Content="{TemplateBinding IndependentValue}"
ContentStringFormat="{}{0:MMMM d, yyyy}"/>
<ContentControl Content="{TemplateBinding DependentValue}"
ContentStringFormat="Visits {0:###,###,###}"/>
</StackPanel>
</ToolTipService.ToolTip>
<Ellipse StrokeThickness="{TemplateBinding BorderThickness}"
Stroke="{TemplateBinding BorderBrush}"
Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Real Time Graph" VerticalAlignment="Top" Grid.Row="0" />
<chartingToolkit:Chart Grid.Row="1"
Name="RTGraph"
BorderThickness="0" >
</chartingToolkit:Chart>
</Grid>
</Grid>
</DockPanel>
</Window>
As SeeSharp says, Snoop allows you to view the object tree at runtime (and change values and see results etc). However, I think your problem here might be that you're not explicitly applying the style on the <chartingToolkit:Chart /> object.
Try one of the following to see if it makes a difference:
Apply style on object:
<chartingToolkit:Chart
...
Style="{DynamicResource GoogleLineDataPointStyle}"
...
>
Or remove the key from the style so that it only has a TargetType attribute (should make it the default style for all objects of that type:
<Style TargetType="chartingToolkit:LineDataPoint">
...
</Style>
Since you've given the styles an x:Key. you need to explicitly set the style property of your items to use that style as a resource.
Have you tried removing the x:Key properties from your style, and moving your style declaration from the grid and into the chart?
See output window in VS. All binding errors logged in this window. Also, tool Snoop alow to see bindings with errors.
If this is a WPF application, i would like to suggest one silly thing. Excuse me for that. Please copy and paste the same code into a silverlight application and then inspect the element using Firebug.
Also, in your code snippet, i think you need to give :
TargetType="{x:Type Polyline}"
TargetType="{x:Type chartingToolkit:LineDataPoint}"
If you want these styles to be applied on the target type automatically, then remove the x:Key.
Also, you can find a list of useful WPF utilities # http://www.simple-talk.com/dotnet/.net-tools/essential-tools-for-the-wpf-novice/

Categories

Resources