Parse Exception occurring due to my Styling - c#

I am creating a WPF application in C# using XAML. I have looked into the documentation of creating Styles for XAML.
It looks to be working correctly in the Designer before I actually run my application. Upon running my application I receive a parse exception. Looking at the line and position indicated, <Style="{StaticResource T}" /> is the cause of this error. Removing it solves the issue, but this requires me to do an inline Style which I would like to avoid.
The XAML code for the Page encountering this issue is below and I would appreciate any feedback and guidance on this issue. The Style not working here is the x:Key="T" TargetType="Border".
<Page x:Class="NGClient1.Screen1.BE2.WindowBe2Tablet"
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:NGClient1.Screen1.BE2"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="WindowBe2Tablet" Width="1024" Height="1280" Background="Black">
<Grid>
<Grid>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Source="Resources/backdrop.png" Stretch="UniformToFill" Grid.ColumnSpan="2" Grid.RowSpan="3" />
<StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Advert Section Here" />
</StackPanel>
<Border Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" BorderBrush="White" BorderThickness="4" Background="Black" Margin="40, 40, 40, 40" Opacity="0.5"/> -->
<Border Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Style="{StaticResource T}" /> <!-- Exception being thrown here, unsure why -->
<StackPanel Grid.Column="0" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Lower Section Left Here" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Lower Section Right Here" />
</StackPanel>
</Grid>
</Grid>
<Page.Resources>
<Style x:Key="T" TargetType="Border" > <!-- x:Key causing exception, unsure why -->
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="Background" Value="Black"/>
<Setter Property="Margin" Value="40, 40, 40, 40"/>
<Setter Property="Opacity" Value="0.5"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="25"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Page.Resources>
</Page>

When using StaticResources, the order of defining and referencing a resource in XAML matters.
Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.
As stated in the documentation for static resource lookup:
Forward references cannot be resolved by a static resource reference.
In your case, the resource section is at the bottom of the page, so the resource will be defined after it is first referenced through StaticResource. In order to solve the issue, you have to either move the resources section to a position before resources defined within it are referenced or use DynamicResource instead.
<Border Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Style="{DynamicResource T}"/>
The DynamicResource Markup Extension instead processes a key by creating an expression, and that expression remains unevaluated until the app runs, at which time the expression is evaluated to provide a value.

Related

Convert static XAML inline styles to external CSS style sheet

To start I am not familiar with XAML however I know XML/CSS exceptionally well. I've begun helping a friend add some style to their XAML application though very quickly noticed that all of their styling is inline which is a nightmare. Here is a good chunk of their code:
add-type -AssemblyName System.Windows.Controls.Ribbon, PresentationFramework
[xml]$xaml = #"
<Window Height="425" Title="TSD-Essentials" Width="1050" x:Name="Window" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:ribbon="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:z="http://www.w3.org/1999/xhtml">
<Grid x:Name="Grid">
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="155"/>
<ColumnDefinition Width="AUTO"/>
<ColumnDefinition Width="AUTO"/>
<ColumnDefinition Width="AUTO"/>
<ColumnDefinition Width="AUTO"/>
</Grid.ColumnDefinitions>
<Grid.Background>
<LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#52618f" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<Label Content="Host Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Width="80" />
<TextBox x:Name = "HostName" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Left" Width="150"></TextBox><!--Enter host name-->
<Label Content="Service Now:" Grid.Column="2" Grid.Row="0" />
<TextBox Grid.Column="3" Grid.Row="0" Width="175" x:Name = "SNtextBox">Search ServiceNow</TextBox>
</Grid>
</Window>
"#
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
$window.ShowDialog()
Now I've attempted to research and add my own style sheet declarations...
External:
<StyleSheet Source="styles.css" />
Internal:
<StyleSheet>
<![CDATA[
TextBox {background-color: #f0f;}
]]>
</StyleSheet>
However I keep getting error messages. The XAML documentation I come across has various elements such as application however my friend is using window. So I don't know if there is versioning involved or not hence why I pasted a large snippet of the code I've begun to clean up.
Exception calling "Load" with "1" argument(s): "Cannot create unknown type '{http://schemas.microsoft.com/winfx/2006/xaml/presentation}StyleSheet'."
I've been reading through documents like the following though all I end up getting are error messages:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/styles/css/#xaml
I'm vaguely aware that this is somehow .NET related (using Windows PowerShell ISE to edit this) though I'm not familiar with this. I simply need to help him get out of inline styling or he'll never get any work done. How can I get a style sheet working and with a simple example of how to change the background-color (or whatever XAML equivalent) to define the background-color of all of the TextBox elements?
I'm not entirely sure if there is an efficient manner of doing this however this does work. I added the Window.Resources element just after the Window element. Here is the code for that:
<Window [...]><!-- Shown for it's relative position in the code. -->
<Window.Resources>
<Style TargetType="TextBox">
<Setter Property="Background" Value="#000" />
<Setter Property="Foreground" Value="#ccc" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontSize" Value="17" />
</Style>
</Window.Resources>
CSS :hover and :focus style appears to be a subset (trying to use minimal code):
<Window.Resources>
<Style TargetType="TextBox">
<!-- CSS background-color -->
<Setter Property="Background" Value="#000" />
<Style.Triggers>
<!-- CSS :hover -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#f0f" />
<Setter Property="Background" Value="#222" />
<Setter Property="Foreground" Value="#fff" />
</Trigger>
<!-- CSS :focus -->
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="BorderBrush" Value="#f0f" />
<Setter Property="Background" Value="#222" />
<Setter Property="Foreground" Value="#fff" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>

How to format chat conversations in markdowntextblock in Windows Universal application (windows 10)

I am building a chat application in which i have below xaml code -
<Page
x:Class="MyProject1.MainPage"
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:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d" Background="Black">
<Grid Background="White" Name="mainGrid">
<Border BorderBrush="Cyan" BorderThickness="0.2" Margin="3,0,3,3">
<ListView x:Name="ListView" VerticalAlignment="Bottom" SelectionMode="None" IsItemClickEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<controls:MarkdownTextBlock Name="markdownBlock" Text="{Binding Text}" TextWrapping="Wrap" FontFamily="Segoe-UI">
</controls:MarkdownTextBlock>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="Black" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Border>
</Grid>
</Page>
I use below code in my code behind to send text to the MarkdownTextBlock control
messages.Add(new Message() { Text = "**Person 1:** " + message });
and the response -
messages.Add(new Message() { Text = "**Person 2:** " + activity.Text });
Right now the format is plain background like below -
Person 1: Hello, How are you doing?
Person 2: Hi, I am doing great!
How can i format these plain messages to get conversation feel like we have in skype as
I am new to Windows Application development, I am not sure how to format the text as conversations within markdown text block, could you guide me?
Do I need to create a table within markdown control and pass the messages by having background color on rows? not sure how to do this. Any help?
Updated view -
<Page
x:Class="MyProject1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gif="using:XamlAnimatedGif"
xmlns:local="using:LISA_Speech1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d" Background="Black">
<Page.Resources>
<Style x:Key="MessageItemStyle" TargetType="SelectorItem">
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="450" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Padding" Value="10" />
<Setter Property="Margin" Value="5" />
</Style>
<Style
x:Key="RightAlignedMessageStyle"
BasedOn="{StaticResource MessageItemStyle}"
TargetType="SelectorItem">
<Setter Property="Background" Value="LightGray" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style
x:Key="LeftAlignedMessageStyle"
BasedOn="{StaticResource MessageItemStyle}"
TargetType="SelectorItem">
<Setter Property="Background" Value="Orange" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<styleSelectors:MessageContainerStyleSelector
x:Key="MessageContainerStyleSelector"
ReceivedStyle="{StaticResource LeftAlignedMessageStyle}"
Sender="{x:Bind CurrentUser, Mode=OneWay}"
SentStyle="{StaticResource RightAlignedMessageStyle}" />
<DataTemplate x:Key="MessageTemplate" x:DataType="messages:Message">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind Message, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<StackPanel
Grid.Row="1"
Margin="0,5,0,0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock
HorizontalAlignment="Right"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind SentDate, Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="MessageItemPanelTemplate">
<ItemsStackPanel VerticalAlignment="Bottom" ItemsUpdatingScrollMode="KeepLastItemInView" />
</ItemsPanelTemplate>
</Page.Resources>
<Grid Background="Black" Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Border BorderBrush="Cyan" BorderThickness="0.2" Margin="3,0,3,3">
<ListView
x:Name="Messages"
Margin="10"
CanDrag="False"
CanReorderItems="False"
IsItemClickEnabled="False"
IsTapEnabled="False"
ItemContainerStyleSelector="{StaticResource MessageContainerStyleSelector}"
ItemTemplate="{StaticResource MessageTemplate}"
ItemsPanel="{StaticResource MessageItemPanelTemplate}"
ItemsSource="{x:Bind Text, Mode=OneWay}" />
</Border>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="35"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox x:Name="text" KeyUp="TextBox_KeyDown" Grid.Column="0" PlaceholderText="Type something or say 'Start Listening'" FontSize="17" BorderBrush="Purple" Margin="0,10,0,-7" Height="58" VerticalAlignment="Top">
</TextBox>
<Button x:Name="button" Click="Button_Click" Grid.Column="1" Height="58" Width="35" Padding="0" Background="Purple" Margin="0,10,0,-7">
<SymbolIcon x:Name="symbol" Symbol="Microphone" Width="35" HorizontalAlignment="Center" Foreground="White" Margin="-2,-8,-2,-2"/>
</Button>
</Grid>
<MediaElement x:Name="Media"></MediaElement>
</Grid>
</Page>
You can achieve this quite simple using an ItemContainerStyleSelector. What this will do is allow you to create some logic that takes your chat message object and determine if it was sent or received.
For example, your model may look like this:
public class Message
{
public Guid Id { get; set; }
public string UserTo { get; set; }
public string UserFrom { get; set; }
public string Message { get; set; }
public DateTime SentDate { get; set; }
}
You then will create the StyleSelector like this:
public class MessageContainerStyleSelector : StyleSelector
{
public Style SentStyle { get; set; }
public Style ReceivedStyle { get; set; }
public string Sender { get; set; }
protected override Style SelectStyleCore(object item, DependencyObject container)
{
var message = item as Message;
if (message != null)
{
return message.UserFrom.Equals(this.Sender, StringComparison.CurrentCultureIgnoreCase)
? this.SentStyle
: this.ReceivedStyle;
}
return base.SelectStyleCore(item, container);
}
}
From here, we then need to create the styles that will be used with this style selector and they are very simple. They will also give you flexibility for the colors you're looking to use for the sent or received messages.
In your view, you may have styles set up like this:
<Page.Resources>
<Style x:Key="MessageItemStyle" TargetType="SelectorItem">
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="450" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Padding" Value="10" />
<Setter Property="Margin" Value="5" />
</Style>
<Style
x:Key="RightAlignedMessageStyle"
BasedOn="{StaticResource MessageItemStyle}"
TargetType="SelectorItem">
<Setter Property="Background" Value="LightGray" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style
x:Key="LeftAlignedMessageStyle"
BasedOn="{StaticResource MessageItemStyle}"
TargetType="SelectorItem">
<Setter Property="Background" Value="Orange" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<styleSelectors:MessageContainerStyleSelector
x:Key="MessageContainerStyleSelector"
ReceivedStyle="{StaticResource LeftAlignedMessageStyle}"
Sender="{x:Bind CurrentUser, Mode=OneWay}"
SentStyle="{StaticResource RightAlignedMessageStyle}" />
<DataTemplate x:Key="MessageTemplate" x:DataType="messages:Message">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind Message, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<StackPanel
Grid.Row="1"
Margin="0,5,0,0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock
HorizontalAlignment="Right"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind SentDate, Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="MessageItemPanelTemplate">
<ItemsStackPanel VerticalAlignment="Bottom" ItemsUpdatingScrollMode="KeepLastItemInView" />
</ItemsPanelTemplate>
</Page.Resources>
In these styles, you see that we are using a base style which the two chat message styles inherit from. We are using a right/left alignment in this scenario so your messages will show on either side of the screen but here you can customize each style to your own needs.
A few other things to point out here, we are also declaring the DataTemplate that will be used to show layout the message. Notice here we aren't doing anything custom. Every message will layout the same, it's the container style that will alter how they appear in the ListView.
Also the ItemsPanelTemplate at the bottom allows the ListView to present the messages bottom up in a chat style format.
In regards to how this all ties together with your ListView in the page, you would now use the MessageContainerStyleSelector like this:
<ListView
x:Name="Messages"
Margin="10"
CanDrag="False"
CanReorderItems="False"
IsItemClickEnabled="False"
IsTapEnabled="False"
ItemContainerStyleSelector="{StaticResource MessageContainerStyleSelector}"
ItemTemplate="{StaticResource MessageTemplate}"
ItemsPanel="{StaticResource MessageItemPanelTemplate}"
ItemsSource="{x:Bind Messages, Mode=OneWay}" />
When you're running the app, you'll get something that looks similar to this:
Hopefully this is something to go off and you can take this further with this detail. Feel free to ask any questions, I'm happy to help.
The first thing I would do is a custom control called MessageViewer. In this one you could have a parameter that tells you what's the direction of the message, or just two another classes MessageViewerIn and MessageViewerOut that could be like this:
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1" Fill="LightBlue" RadiusX="15" RadiusY="15"></Rectangle>
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10" Text="Some dummy text here"></TextBlock>
</Grid>
Now, via code you could understand if you need an image on the LEFT or RIGHT column of this grid. Everything will depend if the text you're showing is from an user or if YOU are sending this text.
So, you could add some methods to check it (or directly do in in the constructor of this class like:
MessageViewer(String message, bool orientation)
MessageViewer msgVwr = new MessageViewer("Your Text", true/false)
...and if its true your icon will be on the left, and when it's false on the right. Inside of the control you can access various element, so for example, if you'll give a name for a grid
<Grid Name="grdMain">
you can acces his properties via code, like grdMain.Background, and set it and change it.
For the space on the left/right you could use margins of the interlat textbox, setted on "10, 10, 30, 10" for right-space (yours) messages and "30, 10, 10, 10" for left-space (incoming) messages.
For doing some text work, like bold or other, check out elements you can put inside a grid: everything you want :)
All this elements you could put in a simple ListView to show them like a chat.

Writing a "Progress Pie" style for WPF ProgressBar

I'm trying to write a WPF style for ProgressBar that turns the standard bar in a "Progress pie".
This is what I've tried so far:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Style x:Key="ProgressPie" TargetType="{x:Type ProgressBar}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid x:Name="TemplateRoot" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="PART_Track"
Fill="{TemplateBinding Background}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ed:Arc x:Name="PART_Indicator"
ArcThickness="1"
ArcThicknessUnit="Percent"
Fill="{StaticResource SomeStaticBrush}"
ToolTip="{TemplateBinding Value}"
EndAngle="{TemplateBinding Value}"/>
<ed:Arc x:Name="OuterPieBorder"
ArcThickness="{TemplateBinding BorderThickness}"
ArcThicknessUnit="Pixel"
Stroke="{TemplateBinding BorderBrush}"
StartAngle="0"
EndAngle="360"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Unfortunately I have at least a couple problems:
It seems that the width of PART_Indicator is bound to the Value of the template. How come? I haven't written anything to do so.
I can't find a simple way to position PART_Indicator so that the center of the pie coincides with the center of PART_Track; any suggestions?
It seems that the width of PART_Indicator is bound to the Value of the template. How come? I haven't written anything to do so.
That is how templates works :) see this for more explanations.
Regarding your second question I dont see any "magic answer" (I guess there isnt), but this answer might help you.
If you can read french, or you trust google translate, there is this one as well which does what you want, and seems pretty complete.

Dynamically change style of element with C#

I have a chart with 4x LineSeries. I defined two different styles for representing the lines, and I want to be able to change the style applied to a particular LineSeries dynamically (based, for example, on the user tapping a button, etc).
I cannot seem to work out how to update the style from c#. Any help appreciated!
I have tried:
lineChartMood.PolylineStyle = this.Resources.PolylineStyle2 as Style;
but this returns a Null exception.
Here is the XAML for the page, including the style definitions:
<phone:PhoneApplicationPage
x:Class="Bhutaan.ChartingTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:local="clr-namespace:Bhutaan"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<Style x:Key="PolylineStyle" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="5"/>
</Style>
<Style x:Key="PolylineStyle2" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="1"/>
</Style>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="TEST" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="added" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,-0,12,0">
<ScrollViewer>
<StackPanel>
<TextBlock Text="Great! That's been saved." FontSize="30" Margin="0,0,0,0"/>
<!-- Chart -->
<charting:Chart
x:Name="myChart"
Margin="0,20,0,0"
Height="350"
Style="{StaticResource PhoneChartStyle}"
Template="{StaticResource PhoneChartPortraitTemplate}">
<!-- Series -->
<charting:LineSeries
x:Name="lineChartMood"
Title="Mood"
ItemsSource="{Binding}"
DependentValuePath="MoodValue"
IndependentValuePath="Timestamp"
PolylineStyle="{StaticResource PolylineStyle}" >
<charting:LineSeries.LegendItemStyle>
<Style TargetType="charting:LegendItem">
<Setter Property="Margin" Value="5 0 5 0"/>
</Style>
</charting:LineSeries.LegendItemStyle>
</charting:LineSeries>
<!-- Series -->
<charting:LineSeries
Title="Energy"
ItemsSource="{Binding}"
DependentValuePath="EnergyValue"
IndependentValuePath="Timestamp">
<charting:LineSeries.LegendItemStyle>
<Style TargetType="charting:LegendItem">
<Setter Property="Margin" Value="5 0 5 0"/>
</Style>
</charting:LineSeries.LegendItemStyle>
</charting:LineSeries>
<!-- Series -->
<charting:LineSeries
Title="Mental"
ItemsSource="{Binding}"
DependentValuePath="MentalValue"
IndependentValuePath="Timestamp">
<charting:LineSeries.LegendItemStyle>
<Style TargetType="charting:LegendItem">
<Setter Property="Margin" Value="5 0 5 0"/>
</Style>
</charting:LineSeries.LegendItemStyle>
</charting:LineSeries>
<!-- Series -->
<charting:LineSeries
Title="Hunger"
ItemsSource="{Binding}"
DependentValuePath="HungerValue"
IndependentValuePath="Timestamp">
<charting:LineSeries.LegendItemStyle>
<Style TargetType="charting:LegendItem">
<Setter Property="Margin" Value="5 0 5 0"/>
</Style>
</charting:LineSeries.LegendItemStyle>
</charting:LineSeries>
</charting:Chart>
</StackPanel>
</ScrollViewer>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
I tested your code and found the cause of the problem.
You get the NullReferenceException because the field this.lineChartMood isn't set by the application for some unknown reason.
You have to obtain this line series object by yourself. There are two possible ways to get it:
var lineSeriesWay1 = this.FindName("lineChartMood");
var lineSeriesWay2 = myChart.Series.OfType<LineSeries>().First(ls => ls.Name == "lineChartMood");
But I would recommend to set the field this.lineSeriesMood explicitly in the constructor, like this:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// because the code 'this.FindName("lineChartMood")' doesn't work in the constructor, I'll use the following line:
this.lineChartMood = this.myChart.Series.OfType<LineSeries>().First(ls => ls.Name == "lineChartMood");
// other code
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.lineChartMood.PolylineStyle = (Style)this.Resources["PolylineStyle2"];
this.lineChartMood.Refresh(); // you should call this method so that the style is applied
}
}
Then you will be able to reference to your series without exceptions.
Why not add your resources in the App.xaml and refer them using App.Current.Resources?? I say this because I feel the program might not be able to refer the local resource defined on the specific page. I might be wrong. This is not a solution just a workaround.
lineChartMood.PolylineStyle = this.Resources.PolylineStyle2 as Style;
should be
lineChartMood.PolylineStyle = this.Resources["PolylineStyle2"] as Style;??

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