I am using the WPF Toolkit (System.Windows.Controls.DataVisualization.Toolkit) to generate a simple chart. In order to set my Y-axis to start from a value of zero, I set the Chart.Axes property like so:
<chartingToolkit:Chart Width="800" Height="400" Title="Usage" Style="{StaticResource ChartStyle}">
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="Y" Minimum="0" />
</chartingToolkit:Chart.Axes>
<chartingToolkit:LineSeries DependentValuePath="Value" IndependentValuePath="Key" ItemsSource="{Binding Data}" />
</chartingToolkit:Chart>
This works fine. However, when I try to set this property through a Style, intellisense does not even show Axes.
<Style x:Key="ChartStyle" TargetType="{x:Type chartingToolkit:Chart}">
<Setter Property="Axes">
<Setter.Value>
<chartingToolkit:LinearAxis Orientation="Y" Minimum="0" />
</Setter.Value>
</Setter>
</Style>
If I run the code, I get an ArgumentNullException saying Property cannot be null. This is Style.Setter.Property. I looked into the source code at Codeplex and found the Axes property:
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Setter is public to work around a limitation with the XAML editing tools.")]
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value", Justification = "Setter is public to work around a limitation with the XAML editing tools.")]
public Collection<IAxis> Axes
{
get
{
return _axes;
}
set
{
throw new NotSupportedException(Properties.Resources.Chart_Axes_SetterNotSupported);
}
}
It says here that Setter is public but I cannot find any such public method. Now my questions are:
How is setting the property through a Style technically different from the first block of code in this question?
Is there a way I can set the Axes property through a Style?
Should I still be using the WPF Toolkit for charts? Is there a newer "canon" method to generate charts that I am not aware of?
you're close :)
You have to attach the style to the linearAxis itself, as there is not accessor from the chart style.
Style goes like this:
<Style x:Key="linearAxisStyle" TargetType="{x:Type charting:LinearAxis}">
<Setter Property="Orientation" Value="Y" />
<Setter Property="Minimum" Value="0" />
</Style>
Binding goes like this:
<chartingToolkit:Chart Width="800" Height="400" Title="Usage" Style="{StaticResource ChartStyle}">
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Style="{StaticResource linearAxisStyle}" />
<chartingToolkit:Chart.Axes/>
<chartingToolkit:LineSeries DependentValuePath="Value" IndependentValuePath="Key" ItemsSource="{Binding Data}" />
I'm answering in a new item since you changed the request....
You expect the default syntax to be something like this:
<Style x:Key="linearAxisStyle_Alt" TargetType="{x:Type charting:Chart}">
<Setter Property="Axes">
<Setter.Value>
<Setter Property="LinearAxis">
<Setter.Value>
<charting:LinearAxis Orientation="Y" Minimum="0" />
</Setter.Value>
</Setter>
</Setter.Value>
</Setter>
</Style>
The problem (which actually isnt one) is that the "Axes"-element doesn't have a style-property. Therefore you can not set a style inherited by its child - the LinearAxis.
That's why you receive the error: "property can not be null". Of course it cannot, cause its not existing.
So the final answer to your request is - (unfortunatly) its not possible.
Hopefully this gives you a better understanding.
Related
I'm currently looking at the UWP CommunityToolkit DataGrid. I've been through the docs, but I'm not finding them clear on how to apply a ColumnHeaderStyle. I'm not sure what I should be targeting in the column header to set my style. I'm wishing to change the background and foreground colors. I would also like these properties to apply across the whole header, not just individual columns.
<controls:DataGrid.ColumnHeaderStyle>
<Style TargetType="">
<Setter Property="" Value=""/>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
This one had me puzzled for a while, but I eventually discovered you need to add another XML namespace declaration in order to target the column header.
<Application
x:Class="MyApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:controlsprimitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives">
So in this case I just appended:
xmlns:controlsprimitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives"
Then you can create a style with this target:
<Style x:Key="ColumnHeaderStyle" TargetType="controlsprimitives:DataGridColumnHeader">
<!-- style properties -->
</Style>
(As of writing this, however, there seems to be weird styling behavior in doing this for some reason.)
You can override DataGridColumnHeaderBackgroundBrush and DataGridColumnHeaderForegroundBrush in your App.xaml as below:
<SolidColorBrush x:Key="DataGridColumnHeaderBackgroundBrush" Color="#FFCB2128" />
<SolidColorBrush x:Key="DataGridColumnHeaderForegroundBrush" Color="#FFB03060" />
The answer from #user1559112 got me on the right track, but it took some time to realize that in order to deal with the "weird styling behavior", it wasn't enough to just add a setter for the Background. I had to override the template like this:
<controls:DataGrid.ColumnHeaderStyle>
<Style TargetType="controlsprimitives:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="prms:DataGridColumnHeader">
<ContentPresenter Background="{ThemeResource HeaderBackgroundBrush}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
I need to display a number in a square, centered horizontally and vertically.
When I tried to use a label for that purpose, it seemed like it ignored the centering completely. So I decided to use a grid and display a label on the grid as that centers perfectly.
I need to use a template as there's several themes available. From what I've found on the internet, I thought this ( ignoring the centering for now )
<ControlTemplate x:Key="ClockTemplate">
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="White"/>
</Style>
</Grid.Style>
<Label>
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="#376092"/>
</Style>
</Label.Style>
<ContentPresenter/>
</Label>
</Grid>
</ControlTemplate>
would be correct. Using it as follows:
<ContentControl Content="20" Height="64" Width="64" Template="{DynamicResource ClockTemplate}"/>
the content is not displayed tho, what am I doing wrong? Also, is there a better way to achieve my goal?
As per my understanding this is not the correct approach. Instead of creating ControlTemplate you have to write a Style for your control like below, also use StaticResource binding if possible. It is faster than Dynamic binding. Please not that, I have not mentioned the Label size inside the ControlTemplate. Please do it based on your needs
<Style x:Key="ContentControlStyle"
TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid Background="White">
<Label Foreground="#376092"
Width="200"
Height="100" Content="{TemplateBinding Content}">
</Label>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
bind your ContentControl with the newly created Style like below
<ContentControl Style="{StaticResource ContentControlStyle} ">
If your requirement is only to set some value in ContentControl, use Label instead and change the Style of the Label. Because ContentControl is heavy
I know that Silverlight 5 introduces the data binding in styles. I want to bind the source of image which is present in content template in the style of a button.
I am using the below code where I am trying to set the image source property in style.
// Style
<UserControl x:Class="MGPIControls_Simple.ButtonControl"
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:vsm="clr-namespace:System.Windows;assembly=System.Windows"
Height="40" Width="40"
mc:Ignorable="d" x:Name="ButtonControlSample">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.Resources>
<Style x:Key="ImageButtonStyle" TargetType="Button">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!-- binding in style -->
<Image Source="{Binding ImageSource}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Stretch="Fill"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button x:Name="ButtonBase" Style="{StaticResource ImageButtonStyle}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>
Where ImageSource is the dependency property I have created. If I dont bind the image source property and keep it static to some image url the things are working fine but binding is not working. Please let me know where I am wrong in above approach.
You have to use binding like
<TextBlock Text="{Binding Path=DataContext.BusyText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
Well, how to put this... what you try to do is not the new Silverlight 5 feature Binding in Styles. This kind of binding is always possible, even with older Silverlight versions.
You have a DataTemplate and that means any binding you declare is evaluated when actual UI elements are instantiated from the template. And your binding Source="{Binding ImageSource}" is evaluated against your Button's DataContext.
If there is no public property ImageSource then your Button won't show any image.
I have the following XAML (simplified):
<Window ...
<Window.Resources>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="FontSize" Value="28" />
<Setter Property="Margin" Value="3" />
<Setter Property="Foreground" Value="Green" />
</Style>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource=...
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Index}" />
<TextBlock Text="-" />
<TextBlock Text="{Binding Hours, StringFormat={}{0:00}}" />
<TextBlock Text=":" />
<TextBlock Text="{Binding Minutes, StringFormat={}{0:00}}" />
<TextBlock Text=":" />
<TextBlock Text="{Binding Seconds, StringFormat={}{0:00}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
...
With this code the Style defined in the Window.Resources is not being applied to the TextBlock inside the DataTemplate but it is on other TextBlocks on the Window.
If I copy the Style and set it in the DataTemplate resources like this:
<DataTemplate.Resources>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="FontSize" Value="28" />
<Setter Property="Margin" Value="3" />
<Setter Property="Foreground" Value="Green" />
</Style>
</DataTemplate.Resources>
Then it works. Any idea why do I need to duplicate the style?
Thanks in advance.
Implicit Styles will apply in templates only to types that inherit from System.Windows.Controls.Control and since TextBlock inherits directly from System.Windows.FrameworkElement it won't work. You have to either give your style x:Key and use it explicitly or declare your style in Application.Resources but then it will apply to all TextBlocks and by this I mean basically every displayed bit of text, in whole application
It's a WPF quirk. When a control doesn't inherit from Control, but directly from FrameworkElement, implicit style lookup inside a template skips directly to the application resources. If you put the style in the application resources (App.xaml) it would work.
Alternatively, you can use a named resource and BasedOn to reference it:
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource MyTextStyle}" />
</DataTemplate.Resources>
Please take a look DataTemplate and Style Confusion:
I posted this as a "bug" on Connect in October 2006.
...
"This behavior is 'By Design' and this is why. Templates are viewed as an encapsulation boundary. Elements produced by these templates fall within this boundary. And lookup for a style with a matching TargetType stops at this boundary. Hence the TextBlock in the repro which is produced through a template does not pick up the Style in question. Whereas the TextBlock defined outside the template does.
One way to work around this problem is to give an explicit name to the Style and reference the style by this name on the TextBlock within the template.
here is whats getting on my nerve:
My job si to restyle application, so i didn’t wrote it, i have to slightly change the code(.cs or .xaml). Problem lies within avalonDock…i cant remove borders from panels, or change its color.
This is part of code, where dockingManager parts are defined(lets call it MainView.xaml)
<ad:DockingManager Name="dockingManager" >
<ad:ResizingPanel Orientation="Horizontal">
<ad:DockablePane ad:ResizingPanel.ResizeWidth="50" Name="navigatorHostCtrlPane" >
<ad:DockableContent Name="navigatorHostCtrl" Title="{StaticResource Navi}" IsCloseable="False" Background="Transparent"/>
</ad:DockablePane>
<ad:ResizingPanel Orientation="Vertical" >
<ad:DockablePane Name="mainPane" >
<ad:DockableContent x:Name="mainHostCtrl" Title="{StaticResource Sc}" AllowDrop="False" IsCloseable="False" ClipToBounds="False" Background="White"/>
</ad:DockablePane>
<ad:DockablePane ad:ResizingPanel.ResizeHeight="250" >
<ad:DockableContent Name="dataHostCtrl" Title="{StaticResource Dt}" IsCloseable="False" Background="White"/>
</ad:DockablePane>
</ad:ResizingPanel>
</ad:ResizingPanel>
</ad:DockingManager>
And this is where parts are set in .cs file(MainView.xaml.cs) like this:
BindRegionToGui(regionManager, RegionNames.NavigatorRegion, navigatorHostCtrl);
And BindRegionToGui():
private static void BindRegionToGui(IRegionManager regionManager, string regionName, UIElement content)
{
var reg = (AvalonDockRegion)regionManager.Regions[regionName];
reg.Bind(content);
}
I cant change style of outer border even in element by setting BorderThickness = “1“, or in style definition:
<Style x:Key="{x:Type ad:DockablePane}" TargetType="{x:Type ad:DockablePane}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property=“BorderThickness“ Value=“0“/>
</Style>
I can alter whole dockingPanes by setting style like this(after some example):
<Style TargetType="{x:Type ad:DockablePane}">
…
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ad:DockablePane}">
<Border
Background=….
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But with this – the content won’t show up. I assume, that content.template overrides it, but i dont know how i can put application’s defined panels into it.
Sorry if this is stupid question but i am really beginner in xaml / c# so i’m in kind of a bad situation.
I restyled AvalonDock in pretty dumb way. I've downloaded source code from http://avalondock.codeplex.com/SourceControl/list/changesets, changed generic.xaml and rebuild whole library.