Buttons custom content is not rendering at runtime - c#

I have a UserControl hosted in a Windows Forms form. In this UserControl I have a ToolBar where I have various buttons:
<ToolBar>
<Button Content="{StaticResource AllGreenIcon}"/>
<Button Content="{StaticResource AllRedIcon}"/>
<Button Content="{StaticResource RedRectangle}"/>
<Button Content="{StaticResource GreenRectangle}"/>
</ToolBar>
It looks like this in the desinger:
The problem is with the buttons where the icon is made of 4 rectangles. The contents are not rendering for these two buttons at runtime.
It looks like this at runtime:
The code for the AllGreenIcon:
<UserControl.Resources>
<Grid x:Key="AllGreenIcon" Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl Content="{StaticResource GreenRectangle}" Margin="0,0,1,1" Grid.Row="0" Grid.Column="0"/>
<ContentControl Content="{StaticResource GreenRectangle}" Margin="1,0,0,1" Grid.Row="0" Grid.Column="1"/>
<ContentControl Content="{StaticResource GreenRectangle}" Margin="0,1,1,0" Grid.Row="1" Grid.Column="0"/>
<ContentControl Content="{StaticResource GreenRectangle}" Margin="1,1,0,0" Grid.Row="1" Grid.Column="1"/>
</Grid>
</UserControl.Resources>
Does anyone have some ideas how could I fix this?
Thanks in advance!

This common issue is due to WPF (logical) requirement of each UIElement to have a single parent. In your case you are adding to the resources an element - GreenRectangleand then you are using this element as the Content for multiple ContentControls in your AllGreenIcon resource. Each time an element is being connected to the visual tree it will change its parent reference, this guaranties that an element is present only once in the visual tree.
All your green buttons for example will use the same instance of GreenRectangle element. Since each time the GreenRectangle is connected to the visual tree its parent is changed only the last item using the GreenRectange resource will actually display the element.
In conclusion avoid declaring and using UIElements in resources. You should use Styles and Controltemplates.
Note: in your solution the AllGreenIcon grid declared in the resources will have the same problem - cannot be used in two different places in UI at the same time. Use a ContentTemplate instead.
Ex:
<Button ContentTemplate="{StaticResource AllGreenIconTemplate}"/>

I've managed to find a sollution by trial and error. Basicly what I did was I've replaced the ContentControls with Rectangles and made a style for the Rectangles.
<LinearGradientBrush x:Key="GreenLinearGradientBrush" EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF00BD22" Offset="1"/>
<GradientStop Color="#FF218934"/>
</LinearGradientBrush>
<Style x:Key="GreenRectangleStyle" TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="16"/>
<Setter Property="Height" Value="16"/>
<Setter Property="Fill" Value="{StaticResource GreenLinearGradientBrush}"/>
<Setter Property="Effect" Value="{StaticResource IconDropShadowEffect}"/>
</Style>
<Grid x:Key="AllGreenIcon" Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Margin="0,0,1,1" Grid.Row="0" Grid.Column="0" Style="{StaticResource GreenRectangleStyle}"/>
<Rectangle Margin="1,0,0,1" Grid.Row="0" Grid.Column="1" Style="{StaticResource GreenRectangleStyle}"/>
<Rectangle Margin="0,1,1,0" Grid.Row="1" Grid.Column="0" Style="{StaticResource GreenRectangleStyle}"/>
<Rectangle Margin="1,1,0,0" Grid.Row="1" Grid.Column="1" Style="{StaticResource GreenRectangleStyle}"/>
</Grid>
Does anyone have a better solution?
edit:
#Novitchi S had a better solution, based on his answer here is the final version:
<Style x:Key="GreenRectangleStyle" TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="16"/>
<Setter Property="Height" Value="16"/>
<Setter Property="Fill" Value="{StaticResource GreenLinearGradientBrush}"/>
<Setter Property="Effect" Value="{StaticResource IconDropShadowEffect}"/>
</Style>
<DataTemplate x:Key="GreenRectangle">
<Rectangle Style="{StaticResource GreenRectangleStyle}"/>
</DataTemplate>
<DataTemplate x:Key="AllGreenIcon">
<Grid Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="0,0,1,1" Grid.Row="0" Grid.Column="0"/>
<ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="1,0,0,1" Grid.Row="0" Grid.Column="1"/>
<ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="0,1,1,0" Grid.Row="1" Grid.Column="0"/>
<ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="1,1,0,0" Grid.Row="1" Grid.Column="1"/>
</Grid>
</DataTemplate>
.
.
.
<ToolBar>
<Button ContentTemplate="{StaticResource AllGreenIcon}"/>
<Button ContentTemplate="{StaticResource AllRedIcon}"/>
<Button ContentTemplate="{StaticResource RedRectangle}"/>
<Button ContentTemplate="{StaticResource GreenRectangle}"/>
</ToolBar>

Related

WPF: How do I get a text box to fill all available horizontal space?

I'm creating a form in WPF. The form has TextBoxes with TextBlocks to their left. A screenshot with GridLines is below:
I want it to look like this (forgive the MS Paint style):
The problem is: the text boxes are really small unless I set the HorizontalAlignment to Stretch, but if I do that, I can't align them to the left. How do I get the Grid containing TextBlock/TextBox to align to the left and make the TextBox fill all available space?
It's trivially easy if I hardcode widths, but that obviously won't work with resizing. I've tried playing with Stack and Dock Panels to hold the Grids with no luck.
I can't use HorizontalAlignment=Stretch, MaxWidth, and Left aligned at the same time? because there is no other control that is the width of the space I am trying to fill.
I also can't use How to get controls in WPF to fill available space? because nothing in my xaml has HorizontalContentAllignment. I tried wrapping stuff in ContentControls and using an ItemsControl to force it with no luck.
The xaml for the form is below. Note, this xaml is for the control that is under the 'Create' header and to the right of the 3 buttons.
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--Left hand side content goes here-->
<DockPanel Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
Margin="20,0,0,0">
<Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
<ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="Input Name:"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBox Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Center"
Style="{StaticResource FormTextBox}"
Margin="5,0,5,0"/>
</Grid>
<Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
<ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="Input Name:"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBox Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Center"
Style="{StaticResource FormTextBox}"
Margin="5,0,5,0"/>
</Grid>
</DockPanel>
</Grid>
The FormTextBox style is:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox"
x:Key="FormTextBox">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border CornerRadius="10"
Background="{StaticResource InputBrush}">
<Grid>
<Rectangle StrokeThickness="1"/>
<TextBox Margin="1"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Text,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
BorderThickness="0"
Background="Transparent"
VerticalContentAlignment="Center"
Padding="5"
Foreground="{StaticResource TextBrush}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It rounds the corners, changes the background color, and removes the dotted line that shows up if it was selected before you alt-tabbed out and back into the application.
You indicate that this is the desired layout:
There are a few problems with your current code. First, using a DockPanel to host the TextBlock/TextBox pairs, and second, no control has Grid.IsSharedSizeScope=true set on it. You also have defined a shared size for the text box column when in reality you just want it to take up all the available space.
Here is some code that achieves the desired layout:
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--Left hand side content goes here-->
<StackPanel Orientation="Vertical" Grid.Column="1"
Grid.RowSpan="2"
Margin="20,0,0,0"
Grid.IsSharedSizeScope="True" >
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Text" Value="Input Name:"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</StackPanel.Resources>
<Border BorderBrush="Blue" BorderThickness="5">
<Grid ShowGridLines="True" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock/>
<TextBox Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource FormTextBox}"
Margin="5,0,5,0"/>
</Grid>
</Border>
<Border BorderBrush="Red" BorderThickness="5">
<Grid ShowGridLines="True" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock/>
<TextBox Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource FormTextBox}"
Margin="5,0,5,0"/>
</Grid>
</Border>
</StackPanel>
</Grid>
This code produces:
In reality though, if you're going for maximum usability, you'll want to create your own control for the TextBlock/TextBox, and then you could just put it in an ItemsControl of some kind for dynamic content.

Black Background occurs when using microsoft.windows.shell

I am using the microsoft.windows.shell to customize my wpf window chrome. Everything is fine until I added a datagrid. The problem is that the appearance of the window become black sometimes. This situation does not happen constantly! Sometimes it looks fine but sometimes it has a black background.
Here is my xaml code:
<Window x:Class="CodeGeneratorWpf.Config"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Config" Height="300" Width="300" Style="{StaticResource MainWindowStyle}"
WindowStartupLocation="CenterOwner" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<DataGrid Name="dataGrid" Grid.Row="0" ItemsSource="{Binding data}"
AlternatingRowBackground="{StaticResource {x:Static SystemColors.ControlBrushKey}}"
ClipToBounds="True" VerticalGridLinesBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
HorizontalGridLinesBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
LoadingRow="dataGrid_LoadingRow">
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow},
Path=Header}"/>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
</DataGrid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Name="btnSave" Grid.Column="0" Content="Save" Style="{StaticResource EmphasizeButton}" HorizontalAlignment="Stretch" Margin="25,5,25,5" Click="btnSave_Click"/>
<Button Name="btnCancel" Grid.Column="1" Content="Cancel" Style="{StaticResource NormalButton}" Margin="25,5,25,5" Click="btnCancel_Click"/>
</Grid>
</Grid>
</Window>
The MainWindowStyle:
<!--Captions Buttons to control the window borderless-->
<DockPanel Grid.Row="0">
<DockPanel.Background>
<SolidColorBrush Color="#FF5D91DC"></SolidColorBrush>
</DockPanel.Background>
<Image Name="imgTitle" Source="{TemplateBinding Icon}" DockPanel.Dock="Left" Margin="5"></Image>
<Label Content="{TemplateBinding Title}" Foreground="White"></Label>
<ctrl:CaptionButtons Margin="0,0,0,0" Grid.Row="0" HorizontalAlignment="Right" Type="Full"
Foreground="{DynamicResource CaptionButtonColor}" FontSize="14" MarginButton="0,0,5,0"
VerticalAlignment="Center" shell:WindowChrome.IsHitTestVisibleInChrome="True">
</ctrl:CaptionButtons>
</DockPanel>
<ContentPresenter Margin="0" Grid.Row="1" Content="{TemplateBinding Content}"/>
</Grid>
</Border>
</ControlTemplate>
<Style x:Key="MainWindowStyle" TargetType="{x:Type Window}">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome
ResizeBorderThickness="6"
CaptionHeight="25"
CornerRadius="0"
GlassFrameThickness="0,0,0,1" />
</Setter.Value>
</Setter>
<Setter Property="Template" Value="{StaticResource MainWindowControlTemplate}"/>
</Style>
Can I get some help?

DataTrigger in ControlTemplate not setting Image source

I have a ControlTemplate that i defined for showing a View model in my required format. However, I am not able to set the Image's source property from the DataTrigger of the Control Template. Please help me with this.
<ControlTemplate x:Key="GeneralControlTemplate"
TargetType="{x:Type local:ComponentStatisticsControl}">
<Border CornerRadius="3"
BorderThickness="2"
BorderBrush="SkyBlue"
Margin="8,0,0,0">
<Border.Background>
<SolidColorBrush x:Name="ControlBackground" Color="Transparent"/>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Foreground="Blue"
Grid.Row="0"
FontSize="14"
FontWeight="SemiBold"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Path=Title, RelativeSource={RelativeSource TemplatedParent}}"/>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<GroupBox Header="Component Info"
Grid.Row="0"
Foreground="Maroon"
FontWeight="SemiBold">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="IP Address"
Grid.Column="0"
Grid.Row="0"/>
<Label Content="{Binding Path=AdditionalContent.IPAddress, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Row="0"
HorizontalAlignment="Right"
Grid.Column="1"/>
<Label Content="PortNo"
Grid.Column="0"
Grid.Row="1"/>
<Label Content="{Binding Path=AdditionalContent.PortNo, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Row="1"
HorizontalAlignment="Right"
Grid.Column="1"/>
<Label Content="Status"
Grid.Column="0"
Grid.Row="2"/>
<Image Name="imgStatus"
Height="24"
Width="24"
Stretch="Fill"
HorizontalAlignment="Right"
Grid.Column="1"
Grid.Row="2">
</Image>
</Grid>
</GroupBox>
<Expander Header="Queue Statistics"
Grid.Row="1"
ExpandDirection="Down"
IsExpanded="True"
Foreground="DarkOrange"
FontWeight="SemiBold">
<ItemsControl ItemsSource="{Binding Path=AdditionalContent.QueueStatistics, RelativeSource={RelativeSource TemplatedParent}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Grid.IsSharedSizeScope="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type lappmodel:clsQueueStatistics}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ColumnOne"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding QName}"/>
<Label Content="{Binding Count}"
Margin="8,0,0,0"
HorizontalAlignment="Right"
Grid.Column="1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
<GroupBox Header="Connection Statistics"
Foreground="DarkOrange"
Grid.Row="2"
FontWeight="SemiBold">
<ItemsControl ItemsSource="{Binding Path=AdditionalContent.ConnectionInformation, RelativeSource={RelativeSource TemplatedParent}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Grid.IsSharedSizeScope="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type lappmodel:clsComponentConnectionInfo}">
<Border CornerRadius="3"
BorderThickness="1"
BorderBrush="Gray"
x:Name="borderConnectionInfo">
<Border.Background>
<SolidColorBrush Color="Transparent"/>
</Border.Background>
<Grid>
<Grid.Background>
<SolidColorBrush x:Name="gridconnectioninfo"
Color="Transparent"/>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ColumnOne"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Component"
Grid.Row="0"/>
<Label Content="{Binding Identifier}"
Grid.Column="1"
Grid.Row="0"
HorizontalAlignment="Right"/>
<Label Content="Component Id"
Grid.Row="1"/>
<Label Content="{Binding ComponentId}"
Grid.Column="1"
Grid.Row="1"
Foreground="Blue"
HorizontalAlignment="Right"/>
<Label Content="BytesSent"
Grid.Row="2"/>
<Label Content="{Binding BytesSent}"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Right"/>
<Label Content="BytesReceived"
Grid.Row="3"/>
<Label Content="{Binding BytesReceived}"
Grid.Row="3"
Grid.Column="1"
HorizontalAlignment="Right"/>
<Label Content="Connected"
Grid.Row="4"/>
<Image x:Name="imgConnectedStatus"
Grid.Row="4"
Grid.Column="1"
HorizontalAlignment="Right"
Height="24"
Width="24">
</Image>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Source"
TargetName="imgConnectedStatus"
Value="/Resources/GreenDot.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsConnected}" Value="False">
<Setter Property="Source"
TargetName="imgConnectedStatus"
Value="/Resources/red-dot2.png"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard Duration="0:0:0.200"
AutoReverse="True"
RepeatBehavior="Forever">
<ColorAnimation From="Red"
To="DarkRed"
Storyboard.TargetName="borderConnectionInfo"
Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding AdditionalContent.IsComponentShutdown, RelativeSource={RelativeSource TemplatedParent}}"
Value="False">
<Setter TargetName="imgStatus"
Property="Source"
Value="/Resources/GreenDot.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I am trying to set the Source property for imgStatus in the ControlTemplate triggers.
But, there is no change in the Image.
By looking at the following link
http://social.msdn.microsoft.com/Forums/vstudio/en-US/a3bf91a8-e618-41c6-a1ad-be9e19581fd6/datatrigger-inside-controltemplate-issue
It became clear that i should not use TemplatedParent. Setting the {RelativeSource Self} in the binding solved the problem.
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding AdditionalContent.IsComponentShutdown, RelativeSource={RelativeSource Self}}"
Value="False">
<Setter TargetName="imgStatus"
Property="Source"
Value="/Resources/GreenDot.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
fine , wierd contorl design ...
<DataTrigger Binding="{Binding Path=DataContext.IsConnected,
RelativeSource={RelativeSource AncestorType=ItemsControl}}" Value="True">
<Setter Property="Source"
TargetName="imgConnectedStatus"
Value="/Resources/GreenDot.png"/>
</DataTrigger>
since you are using a DataTrigger from an item's precpective , the DataTemplates DataContext is an object from your ItemsSource , RelativeSource to the containing control , Path to it's DataContext.Property

Bing Maps needs a lot of performance when using custom pushpins

I have problems with a .NET 4 application using Bing Maps with custom pushpins. The performance is very bad on zooming or moving the map. I'm using a ObservableCollection which has a data-binding to Bing Maps. Everytime the map changes it is being checked which pushpins are in the map section. The collection will be re-filled and finally a NotifyCollectionChangedEvent is being fired which makes the map draw the pushpins.
<bingMap:MapItemsControl ItemsSource="{Binding Locations}">
<bingMap:MapItemsControl.ItemTemplate>
<DataTemplate>
<bingMap:Pushpin Location="{Binding Coordinates}" Height="Auto" Width="Auto" PositionOrigin="BottomCenter"
Template="{StaticResource PushpinControlTemplateLoc}">
</bingMap:Pushpin>
</DataTemplate>
</bingMap:MapItemsControl.ItemTemplate>
</bingMap:MapItemsControl >
I made some researches with a performance profiler: The InitializeComponent() method of my custom pushpin class needs an average time of 25% to 35%!
There are usually between 10 and 25 custom pushpins displayed on the map. If I reduce the amount of data bindings it becomes a little bit faster, but still not fast enough.
I've already tested out to declare all the brushes as freezed static resources but the drawing still runs very slow.
<SolidColorBrush x:Key="SolidColorBrushUnknownMsg" Color="Gray" ice:Freeze="True" xmlns:ice="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" />
I tried to use the Microsoft default pushpins <bingMap:Pushpin Location="{Binding Coordinates}"/> which was much faster. So there must be something wrong in my usage or implementation of my custom pushpin.
Here's the rest of my code:
Custom pushpin class (only auto-generated code):
public partial class MyPushpin: System.Windows.Controls.Grid
{
public MyPushpin()
{
InitializeComponent();
}
}
Custom pushpin XAML code:
<Grid x:Class="Test.MyPushpin"
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"
mc:Ignorable="d">
<Grid.Resources>
<Style BasedOn="{StaticResource DataTextBlock}" x:Key="test1" TargetType="TextBlock">
<Setter Property="Background" Value="{StaticResource SolidColorBrushErrorMsg}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=TextLine1, Mode=OneWay}" Value="0">
<Setter Property="Background" Value="{StaticResource BackgroundImage}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Border CornerRadius="20" BorderBrush="White" Padding="7" Opacity="0.8" Width="120" Height="100" Background="{StaticResource BackgroundImage}">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="test2" Foreground="Black" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TextLine2, StringFormat=N1,Mode=OneWay}" Style="{StaticResource DataTextBlock}" />
<TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding objCurrentPower.sUnit,Mode=OneWay}" Foreground="Black" />
<!--three more lines of textblocks with data bindings -->
</Grid>
</Border>
Why does my custom pushpin need so much performance?
Problem solved: Instead of using a separate class and xaml and referencing to them it's better to use a ControlTemplate for the custom pushpins in the class the actually contains the Bing Map:
<ControlTemplate x:Key="CutomPushpinTemplate" TargetType="bingMap:Pushpin">
<Border CornerRadius="15" BorderBrush="White" Padding="7" Opacity="0.8" Width="120" Height="90" Background="{StaticResource Bgr_enercon}">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="16" />
<RowDefinition Height="16" />
<RowDefinition Height="16" />
<RowDefinition Height="16" />
<RowDefinition Height="16" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45" />
<ColumnDefinition Width="32" />
<ColumnDefinition Width="23" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="test2" Foreground="Black" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TextLine2, StringFormat=N1,Mode=OneWay}" Style="{StaticResource DataTextBlock}" />
<TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding objCurrentPower.sUnit,Mode=OneWay}" Foreground="Black" />
<!--three more lines of textblocks with data bindings -->
</Grid>
</Border>
</ControlTemplate>
This template is used for all pushpins of the Bing Map this way:
<bingMap:MapItemsControl ItemsSource="{Binding Locations}">
<bingMap:MapItemsControl.ItemTemplate>
<DataTemplate>
<bingMap:Pushpin Location="{Binding objCoordinates}" Height="Auto" Width="Auto" PositionOrigin="BottomCenter" Template="{StaticResource CutomPushpinTemplate}">
</bingMap:Pushpin>
</DataTemplate>
</bingMap:MapItemsControl.ItemTemplate>
Doing it that way is much faster. The performance profiler shows that the programm now does not spend so much time for instantiating the custom pushpins.
Here is the xaml code which shows how it was implemented before (slow):
<ControlTemplate x:Key="PushpinControlTemplateLoc" TargetType="bingMap:Pushpin" >
<Test.MyPushpin />
</ControlTemplate>

Grid Border / Gap between cells

I've created a ControlTemplate that contains a Grid with two rows.
Sadly, there appears to be a single pixel gap between the cells.
How do I remove the gap?
Here's a screenshot showing the gap:
...and here's the XAML:
<Window x:Class="MAQButtonTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="695" Width="996">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="OverridesDefaultStyle" Value="True"/>
</Style>
<ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
<Grid Width="444" Margin="0" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97">
<TextBlock>This is the first piece of text</TextBlock>
</Grid>
<Grid Grid.Row="1" Background="#5898c0">
<ContentPresenter Grid.Row="0" />
</Grid>
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="#e9f1f6"></Grid>
<Grid Grid.Column="1" Background="#d2e3ed">
<StackPanel>
<TextBlock FontFamily="Segoe UI" FontSize="22" FontWeight="Medium" Margin="52,58,0,0" Foreground="#0c3d5d">Your Quizzes <TextBlock FontFamily="Segoe UI" FontSize="18" FontWeight="Medium" Foreground="#0c3d5d">(7)</TextBlock></TextBlock>
<Grid Margin="0,20,0,0">
<Button Width="444" Background="{x:Null}" BorderThickness="0" Template="{StaticResource ButtonTemplate}" Click="DoSomething" BorderBrush="#032135">
<TextBlock Margin="6,2.8,0,0" FontFamily="Segoe UI" FontSize="19" Foreground="#032135" FontWeight="Medium">This is a second piece of text</TextBlock>
</Button>
</Grid>
</StackPanel>
</Grid>
</Grid>
</Window>
Just add SnapsToDevicePixels="True" in your template grid
<ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
<Grid Width="444" Margin="0" ShowGridLines="False" SnapsToDevicePixels="True">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97">
<TextBlock>This is the first piece of text</TextBlock>
</Grid>
<Grid Grid.Row="1" Background="#5898c0">
<ContentPresenter Grid.Row="0" />
</Grid>
</Grid>
</ControlTemplate>
Set
SnapsToDevicePixels="True"
On grids in template or button, but better just create new style with SnapsToDevicePixels="True" setter and template inside style.

Categories