wpf - why does this XAML override template not work - c#

Any ideas regarding why the WPF XAML code I have is not working. I'm trying to override the WPFToolkit charting display, and have taken their default XAML and included in my Grid.Resources section as a means of overriding. Specifically I'm wanting to remove the graph markers, but this specific question pertains to clarifying my understanding of XAML by asking why these specific approaches do not work:
a) - I've tried putting Visibility="Hidden in the Grid element but this doesn't seem to work? Why would this be?
b) tried taking out all the lines in the tag, however this doesn't work. Why would this be? Should this not override things. I'm wondering if my whole override template here is really working at all for LineDataPoint? (I do note that the LineSeries override I have in the below code however do work)
XAML is:
<!-- charting:LineSeries -->
<Style TargetType="chartingToolkit:LineSeries">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="PolylineStyle">
<Setter.Value>
<Style TargetType="Polyline">
<Setter Property="StrokeThickness" Value="1" />
</Style>
</Setter.Value>
</Setter>
</Style>
<!-- charting:LineDataPoint -->
<Style TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Background" Value="Orange" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Width" Value="2" />
<Setter Property="Height" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="0" Visibility="Hidden">
<Ellipse Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" Height="30"/>
<Ellipse RenderTransformOrigin="0.661,0.321">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.681,0.308">
<GradientStop Color="Green" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse x:Name="SelectionHighlight" Opacity="0" Fill="Red" />
<Ellipse x:Name="MouseOverHighlight" Opacity="0" Fill="White" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<chartingToolkit:Chart Title="Engine Performance">
<!-- Power curve -->
<chartingToolkit:LineSeries
Title="Power"
ItemsSource="{StaticResource EngineMeasurementCollection}"
IndependentValueBinding="{Binding Speed}"
DependentValueBinding="{Binding Power}">
<!-- Vertical axis for power curve -->
<chartingToolkit:LineSeries.DependentRangeAxis>
<chartingToolkit:LinearAxis
Orientation="Y"
Title="Power (hp)"
Minimum="0"
Maximum="250"
Interval="50"
ShowGridLines="True"/>
</chartingToolkit:LineSeries.DependentRangeAxis>
</chartingToolkit:LineSeries>
<!-- Torque curve -->
<chartingToolkit:LineSeries
Title="Torque"
ItemsSource="{StaticResource EngineMeasurementCollection}"
IndependentValueBinding="{Binding Speed}"
DependentValueBinding="{Binding Torque}">
<!-- Vertical axis for torque curve -->
<chartingToolkit:LineSeries.DependentRangeAxis>
<chartingToolkit:LinearAxis
Orientation="Y"
Title="Torque (lb-ft)"
Minimum="50"
Maximum="300"
Interval="50"/>
</chartingToolkit:LineSeries.DependentRangeAxis>
</chartingToolkit:LineSeries>
<chartingToolkit:Chart.Axes>
<!-- Shared horizontal axis -->
<chartingToolkit:LinearAxis
Orientation="X"
Title="Speed (rpm)"
Interval="1000"
ShowGridLines="True"/>
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart>
</Grid>
EDIT:
PS. I've boiled it down to the fact the template isn't picked up it seem in the code below - but it should be picked up no? i.e. I have NOT set an x:key against
<Window x:Class="MyInternetUsage.EnginePerformance"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" xmlns:local="clr-namespace:DataVisualizationDemos" xmlns:datavis="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit" Title="EnginePerformance" Height="277" Width="371">
<Grid>
<Grid.Resources>
<local:EngineMeasurementCollection x:Key="EngineMeasurementCollection"/>
<!-- charting:LineDataPoint -->
<Style TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Background" Value="Orange" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
<Grid
Width="30"
Height="30"
Background="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<chartingToolkit:Chart Title="Engine Performance">
<!-- Power curve -->
<chartingToolkit:LineSeries
Title="Power"
ItemsSource="{StaticResource EngineMeasurementCollection}"
IndependentValueBinding="{Binding Speed}"
DependentValueBinding="{Binding Power}">
</chartingToolkit:LineSeries>
</chartingToolkit:Chart>
</Grid>
</Window>
thanks

It is possible that the LineDataPoint is not templatable or at least not fully, by virtue of having many of its style properties defined internally.
You can set a default style as you've done, and this works very well for the "lookless" controls that are part of the framework, because they are designed with templating in mind (and so make use of TemplateBindings), but if a control, for example, declares internally that its background is purple, you cannot override this with a style.
It is also possible that what you're seeing is not actually the background of the control itself, rather the background of a constituent control within. If the component designed does not "pass through" the property, setting values on the control itself won't affect the internal parts that you see.
Finally, it is possible that Chart defines a default style for LineDataPoint. Being in a narrower scope than your grid resource, this would take precedence.
If you have access to the source, you can suss this out; without the source or good documentation of the component, it is just a frustrating trial-and-error guessing game as to what is going on.

Related

WPF: PART_ContentHost not scrolling

I am trying to make a Log area within my application and the customer has requested the ability to cut/paste the log messages from this area.
I originally was using the following to setup the log area with scrolling, but this does not allow the user to select & copy text:
<ScrollViewer DataContext="{StaticResource Log}"
Content="{Binding Appender.Notification}"
Height="150">
<ScrollViewer.Resources>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
</Style>
</ScrollViewer.Resources>
</ScrollViewer>
I found this solution to create a read only TextBox with select-able text:
<TextBox Name="LoggingTextBox"
Height="250"
Width="950"
DataContext="{StaticResource Log}"
Text="{Binding Appender.Notification}"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="PART_ContentHost" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
This works to allow the selection of text within the log area but the scrolling does not work. I added the properties for *ScrollBarVisibility (not in the original solution).
How can I get the scrolling to work using this TextBox styling?
The fix is pretty simple: just change your Border to a ScrollViewer, and you will get the standard scrolling behavior for a TextBox.

How do I remove the X axis labels from this chart?

Keeping myself concise and to the point I wish to remove the labels or at the very least modify them from my X-Axis :
I seem to be using a modified version of this library that allows me to use some tools usually won't work in wp7.
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
This is the LineSeries definitions as of right now :
<charting:Chart x:Name="chart" Title="Humidity Readings" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Foreground="#FF3C58C8">
<chartingToolkit:LineSeries x:Name="HumidityGraph" Title="Humidity" BorderThickness="2" ItemsSource="{Binding Data}" IndependentValuePath="Time" DependentValuePath="Measurement"/>
</charting:Chart>
In response to chridam I tried implementing his suggestion - No succes.
<charting:Chart x:Name="chart" Title="Humidity Readings" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Foreground="#FF3C58C8">
<charting:Chart.LegendStyle>
<Style TargetType="visualizationToolkit:Legend">
<Setter Property="Width" Value="0"/>
<Setter Property="Height" Value="0"/>
</Style>
</charting:Chart.LegendStyle>
<!--there doesn't seem to be an AxisLabelStyle that I can create a style in.-->
<Style x:Key="EmptyStyle" TargetType="charting:NumericAxisLabel">
<Setter Property="StringFormat" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:NumericAxisLabel">
<TextBlock />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<chartingToolkit:LineSeries x:Name="HumidityGraph" Title="Humidity" BorderThickness="2" ItemsSource="{Binding Data}" IndependentValuePath="Time" DependentValuePath="Measurement" TransitionDuration="0:1:1.5" FontSize="18.667">
<charting:LinearAxis AxisLabelStyle="{StaticResource EmptyStyle}" Orientation="X" ShowGridLines="True"/>
</chartingToolkit:LineSeries>
</charting:Chart>
Try specifying a style for Axis Label that sets the StringFormat property value to empty
<chartingToolkit:CategoryAxis>
<chartingToolkit:CategoryAxis.AxisLabelStyle>
<Style TargetType="AxisLabel">
<Setter Property="StringFormat" Value=""></Setter>
</Style>
</chartingToolkit:CategoryAxis.AxisLabelStyle>
</chartingToolkit:CategoryAxis>
Update:
Another alternative is to apply the style template
<Style x:Key="EmptyStyle" TargetType="charting:NumericAxisLabel">
<Setter Property="StringFormat" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:NumericAxisLabel">
<TextBlock />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
to this:
<charting:LineSeries.DependentRangeAxis>
<charting:LinearAxis AxisLabelStyle="{StaticResource EmptyStyle}"
Orientation="X"
ShowGridLines="True"/>
</charting:LineSeries.DependentRangeAxis>
For more resources on styling the chart, Styling a Silverlight Chart

ContentControl Rotate decorator rendering

I have recently stumbled upon following issue: In my WPF application I've implemented a little designer, where you can put elements on canvas, move, scale and rotate them.
While searching the web I found following solution to this problem . This solution implements moving, scaling and rotating by System.Windows.Controls.Primitives.Thumb class so I thought I would just adjust this solution to my app and move on. The problem is, while on my machine everything is fine, on the others there are some rendering problems. I've made a screen shot of what I'm saying:
I'm using Windows 7 even though I run my app on other Windows 7 and it is also rendered wrong. I run my app with Windows XP and other compatibility settings on my machine but I wasn't able to reproduce this bug. What is this about and what am I possibly doing wrong?
This is my xaml file I'm using for content control styling:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:COMPANY.WPUI.LayoutDesignModel.Thumbs">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MoveThumb.xaml"/>
<ResourceDictionary Source="ResizeDecorator.xaml"/>
<ResourceDictionary Source="RotateDecorator.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="DesignerItemStyle" TargetType="ContentControl">
<Setter Property="MinHeight" Value="50"/>
<Setter Property="MinWidth" Value="50"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<Control Name="RotateDecorator" Template="{StaticResource RotateDecoratorTemplate}" Visibility="Collapsed"/>
<s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
<Control x:Name="ResizeDecorator" Template="{StaticResource ResizeDecoratorTemplate}" Visibility="Collapsed"/>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Setter TargetName="ResizeDecorator" Property="Visibility" Value="Visible"/>
<Setter TargetName="RotateDecorator" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
A this is RotateDecorator.xaml file that happens to cause problems:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:COMPANY.WPUI.LayoutDesignModel.Thumbs">
<Style TargetType="{x:Type s:RotateThumb}">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type s:RotateThumb}">
<Grid Width="30" Height="30">
<Ellipse Width="30" Height="30" Fill="#B0B0BB" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="RotateDecoratorTemplate" TargetType="{x:Type Control}">
<Grid>
<s:RotateThumb Margin="-18,-18,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<s:RotateThumb Margin="0,-18,-18,0" VerticalAlignment="Top" HorizontalAlignment="Right" />
<s:RotateThumb Margin="0,0,-18,-18" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
<s:RotateThumb Margin="-18,0,0,-18" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</ResourceDictionary>
The first thing I think of whenever seeing something like this is the graphics cards. You can get some strange behaviors with certain graphics cards, especially if their drivers are not installed properly/up to date.
This is caused by MergedDictionaries. The Diagram Designer Project splits the Move, Resize, and Rotate actions into 3 separate dictionaries. From the screenshot you can see the resize thumb is loaded. In my case the move action also worked, but like the question the rotate thumbs weren't displayed. No errors were thrown, but examination with Snoop shows that it wasn't able to find the rotate dictionary.
This solution expands on what I've covered above: https://stackoverflow.com/a/17083360/978622
To solve: Combine the resource dictionaries into a single resource dictionary.

Creating Layered Custom Control Templates (WPF 4 / .net 4.0 / C#)

I need some help in trying to recreate the following style:
The sea of red can be ignored because it's just the background the textbox is sitting on.
To create the textbox I use the following xaml:
<TextBox Name="tbSorageName"
Grid.Column="1"
Width="250"
Height="30"
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsReadOnly="True"
Style="{StaticResource MainTextBoxStyle}"
Text="{Binding SelectedStorage.Name,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
To style it, I used the following style:
<Style x:Key="MainTextBoxStyle" TargetType="TextBox">
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="Snow" />
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="Background" Value="{DynamicResource MainTextBox_BGBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource MainTextBox_BorderBrush}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="TextAlignment" Value="Left" />
</Style>
The Brushes I use are:
<SolidColorBrush x:Key="MainTextBox_BGBrush" Color="#3A3A3A" />
<SolidColorBrush x:Key="MainTextBox_BorderBrush" Color="#656565" />
That creates the basic textbox I use in my application, but I want to take my design much further by floating some meaningful text that describes the contents of textbox on the right hand side of the text box - So it should be anchored to the right hand side.
You can do this easily via 2 approaches.
1.Create a user control that consists of a textbox and a textblock. The Xaml for the UserControl would look similar to the following
<Grid Width="{Binding Path=Width, ElementName=tbSorageName}" Height="{Binding Path=Height, ElementName=tbSorageName}">
<TextBox Name="tbSorageName"
Grid.Column="1"
Width="250"
Height="30"
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsReadOnly="True"
Style="{StaticResource MainTextBoxStyle}"
Text="hello" />
<TextBlock HorizontalAlignment="Right" Margin="5" Foreground="Red" FontStyle="Italic">Name</TextBlock>
</Grid>
2.Overlay an Adorner on the textbox and draw the description over the Textbox yourself via an OnRender Override.
I would go with the Usercontrol approach since that is cleaner and easier to maintain.

WPF: how to style a class like in css?

Let's say I have a UserControl with 4 Borders:
<Border />
<Border />
<Border />
<Border />
Now in my Resources I can go:
<Style TargetType="{x:Type Border}">
... change some properties here
</Style>
Now this is all good, but it will target all borders in my UserControl.
But what if I just want to target a subset of them?
I'd like to go:
<Border Class="Type1" />
<Border Class="Type1" />
<Border />
<Border />
And then go:
<Style TargetType="{x:Type Border}" TargetClass="Type1">
... change some properties here
</Style>
But this obviously doesn't exist, is there some other way I can achieve what I'm after?
Thanks
Though the syntax isn't quite as clean as in CSS, it is a lot more specific.
To build on your example, what you're looking for is:
<Border Style="{StaticResource Type1}" />
<Border Style="{StaticResource Type1}" />
<Border />
<Border />
And then go:
<Style TargetType="{x:Type Border}" x:Key="Type1">
... change some properties here
</Style>
Remember that WPF styles don't actually cascade like CSS does.
A more detailed styling reference:
https://web.archive.org/web/20141210000517/http://dotnetslackers.com/articles/wpf/StylesResourcesAndControlTemplatesInWPF.aspx
Something that I find most people are not aware of is WPF's ability to nest Styles within Style.Resources. For example:
<!-- Define a new style for Borders called InfoBox, that will have a red background,
and further override all buttons within it to have Yellow Text. An extra style,
"Strawberry" is also defined, that lets specific buttons be selected to be styled
as Green FG on DarkRed BG -->
<Style TargetType="{x:Type Border}" x:Key="InfoBox">
<Setter Property="Background" Value="Red"/>
<Style.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="DarkYellow"/>
</Style>
<Style TargetType="{x:Type Button}" x:Key="Strawberry">
<Setter Property="Foreground" Value="Green"/>
<Setter Property="Background" Value="DarkRed"/>
</Style>
</Style.Resources>
</Style>
...
<Border Style="{DynamicResource InfoBox}">
<StackPanel>
<Button Content="I am a banana!"/>
<Button Style="{DynamicResource Strawberry}" Content="I am red!"/>
</StackPanel>
</Border>
While not exactly the same as CSS (There isn't much support for standard pseudo-selectors), this gives you a huge amount of power and flexibility. Couple this with skillful use of ItemsControls and you can do some great things.
you can set the style directly on the <Border> using an x:key and the StaticResource (or DynamicResource) property of the Border. if you would like to change the style at runtime, then you should lean towards using the DynamicResource over the StaticResource.
<Style x:Key="something" TargetType="{x:Type Border}">
</Style>
<Border style="{StaticResource something}"/>
<Style x:Key="styleKey" TargetType="{x:Type Border}">
... change some properties here
</Style>
and
<Border Style="{StaticResource styleKey}"

Categories

Resources