SciChart: Custom RolloverModifierLabel for multiple DataSeries bound from code - wpf

Before I updated to the latest version of SciChart, I had this custom rollover modifier that displayed multiple values for any given point I "rolled over".
It was implemented like this:
<sci:RolloverModifier
DrawVerticalLine="True"
ShowTooltipOn="Always"
SourceMode="AllVisibleSeries"
TooltipLabelTemplate="{StaticResource RolloverLabelTemplate}" />
RolloverLabelTemplate was a ControlTemplate:
<ControlTemplate
x:Key="RolloverLabelTemplate"
TargetType="sci:TemplatableControl">
<Grid>
...
Now the RolloverModifier.TooltipLabelTemplate is gone from the API and seems to be replaced by TooltipTemplate, which takes a DataTemplate, not a ControlTemplate. I tried making an analogous DataTemplate:
<DataTemplate
x:Key="SomeTemplate"
DataType="s:XySeriesInfo">
<Grid>
But when I try to assign it to the RolloverModifier,
<s:RolloverModifier
...
TooltipTemplate="{StaticResource SomeTemplate}" />
I get the following exception:
Unable to cast object of type
'SciChart.Charting.ChartModifiers.RolloverModifier' to type
'SciChart.Charting.Visuals.RenderableSeries.BaseRenderableSeries'.
I've tried to follow this documentation: https://www.scichart.com/documentation/v4.x/webframe.html#RolloverModifier.html
and on the topic of styling the tooltip template, it suggests to have a RolloverModifier, but to add the TooltipTemplate to the RenderableSeries:
<s:SciChartSurface.RenderableSeries>
<s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}"/>
</s:SciChartSurface.RenderableSeries>
<s:SciChartSurface.ChartModifier>
<s:ModifierGroup>
<s:RolloverModifier ShowTooltipOn="Always" />
</s:ModifierGroup>
</s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
This is a problem for me, because I don't have the RenderableSeries defined in xaml. They are bound to the view model:
<sciVisuals:SciChartSurface
...
SeriesSource="{Binding SciSeries}">
there will be more than one, and in fact I don't even know how many. How can I customize the rollover tooltip label in this case?

In SciChart WPF v4.x or later, it is necessary to apply the TooltipTemplate to the series, because many users requested the ability to individually style series. For example a Candlestick series should have a different tooltip than a Line series.
Please see the SciChart WPF Documentation for applying a RolloverModifier TooltipTemplate in v4+:
Styling the Tooltip Item Template
SciChart by default has a number of Tooltip templates which are unique to the series type.
To change the Tooltip template, use the RolloverModifier.TooltipTemplate attached property:
<s:SciChartSurface >
<s:SciChartSurface.Resources>
<!-- Tooltip Template for an XyDataSeries binds to XySeriesInfo -->
<!-- Check out the properties on XySeriesInfo to see what you can bind to -->
<DataTemplate x:Key="XyTooltipTemplate" DataType="s:XySeriesInfo">
<StackPanel Orientation="Vertical">
<TextBlock Foreground="White">
<Run Text="Series: "/>
<Run Text="{Binding SeriesName, StringFormat='{}{0}:'}"/>
</TextBlock>
<TextBlock Foreground="White">
<Run Text="X-Value: "/>
<Run Text="{Binding FormattedXValue}"/>
</TextBlock>
<TextBlock Foreground="White">
<Run Text="Y-Value: "/>
<Run Text="{Binding FormattedYValue}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</s:SciChartSurface.Resources>
<s:SciChartSurface.RenderableSeries>
<s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}"/>
</s:SciChartSurface.RenderableSeries>
<s:SciChartSurface.ChartModifier>
<s:ModifierGroup>
<s:RolloverModifier ShowTooltipOn="Always" />
</s:ModifierGroup>
</s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
What I suggest in order to style these despite using the MVVM API is to create your styles in XAML and apply them using the SeriesBinding MVVM API.
There is an FAQ in the SciChart WPF Documentation on how to style a tooltip when using the MVVM API here.
A lot of customers ask us how to style various attached properties used in SciChart in the MVVM API. For example, the given following attached properties, how do we convert this to the MVVM API?
The solution is simple, to use our method of Styling the RenderableSeries presented in Worked Example - Style a Series in MVVM.
Simply declare the attached properties and tooltip templates in a style in your View.
Now, apply the style using BaseRenderableSeriesViewModel.StyleKey property. SciChart will pick up the style and do the rest.
If you are still using the older, SeriesSource API (note this is now obsolete as of v4.x) then I suggest declare your style in XAML and apply it using this technique to access a style in code-behind.

Related

Create/Modify new WPF UI components

I want to change the graphical UI elements in WPF.
For example, I want to use a kind of a stack panel, but on the other hand I want to show my details in a star, or circle, etc.
Maybe setting a bitmap as a background, but I am working with lots of Data using zoom tool.
I found tutorials, documentation only for changing attributes of "old components", but nothing to make new ones.
Great resource for WPF beginners is www.wpftutorial.net
One of the best idea of WPF is separation of concerns:
UI Control = Logic in Code/XAML + Template
Using templates in XAML we can vary representation without modifying the control.
For example, if there is a need in creation of list of items. Then we can use ListBox control:
<ListBox>
<ListBoxItem>USA</ListBoxItem>
<ListBoxItem>UK</ListBoxItem>
</ListBox>
By default LisboxItem internal part is just binded TextBlock.
Now making UI modification without changing control source code:
<ListBox ImageSource="{Binding PathToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ProjectIcon}"/>
<TextBlock Text="{Binding Path=PropertyName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
there appears image and text.
If there is a need in creating exclusive control then you can always use Custom Control.
Using raster images (e.g. PNG) is not good point, especially with zoom behaviour. If it is possible better to use vector images, that can be created in XAML or imported from SVG.

Best way to create a list of selectable and deletable items in Windows Phone 7

I want to solve a seemingly simple task. I want to create a list of text entries where each entry is selectable (and causes navigation to another page) and when the user holds his finger over an item I want a context menu with a single option to delete that item. This is very common pattern in WP applications. For example the browser does this with favourites.
Right now I have a listbox with a textblock in the item template and I start the navigation in the SelectionChanged event:
<ListBox Name="lbSnippets" SelectionChanged="lbSnippets_SelectionChanged">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
I can think of several ways to solve the hold problem but none of them sits well with me. For example I may handle the Hold event on the TextBlock but then I will have to dig for the item related to this TextBlock. Something tells me that there should be a better way to do this as it is so common. What is the right way to solve this task?
The Silverlight toolkit for WP7 includes a ContextMenu control.
You can install the toolkit via nuget: PM> Install-Package SilverlightToolkitWP
Then you an add ContextMenus to basically any control:
<DataTemplate>
<TextBlock Text="{Binding}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Delete"
Command="{Binding YourDeleteCommand}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</DataTemplate>
Where toolkit is an xml namespace:
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
You can start learning about the ContextMenu control from this article:
WP7 ContextMenu in depth | Part1: key concepts and API

Place a ContentControl inside a custom control XAML

I created a custom control and what to use a ContentControl inside that control for use of the MVVM design pattern however my control does not like this when I run the application. For testing I also tried other standard controls but none of them work inside the custom control... just more custom controls that are dependant on the parent custom control.
Does anybody suggest how to place standard controls such as the ContentControl inside a custom control?
Cheers.
EDIT
XamlParseException -> 'Add value to collection of type
'System.Collections.ObjectModel.ObservableCollection(Ribbon_Framework.RibbonTabItem)'
threw an exception.' Line number '8' and line position '14'.
<Ribbon:Ribbon AutomaticStateManagement="True" x:Name="Ribbon">
<ContentControl x:Name="SearchRibbon" Content="{Binding Path=SearchRibbon}" ContentTemplate="{DynamicResource SearchRibbonTemplate}" />
</Ribbon:Ribbon>
Inside the contentcontrol ->
<DataTemplate x:Key="SearchRibbonTemplate">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ribbon:RibbonTabItem Header="Search">
<Ribbon:RibbonGroupBox Header="{Binding Path=DisplayName}" Width="100">
<Ribbon:Button Width="100" Icon="{Binding Path=TemplateResource}" LargeIcon="{Binding Path=TemplateResource}" Command="{Binding Path=Commands}" />
</Ribbon:RibbonGroupBox>
</Ribbon:RibbonTabItem>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
Your Ribbon control expects an object of RibbonTabItem type (since it houses an
ObservableCollection<RibbonTabItem>
so you can only add the RibbonTabItem class to it - you need to make sure your control allows other elements inside it. Some 3rd party controls get round this by providing a content control inside the inner item of their custom control (i.e. let RibbonTabItem have a ContentControl inside it) or allow you to customise the item template
You need to change your implementation of Ribbon or change the functionality of RibbonTabItem for this to work. Look at ItemsControl.Items property and see what type that is. You should try using that type for your ObservableCollection

Prevent writing a lot of duplicate code in XAML

I have XAML:
<TextBlock Text="Param 1 name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding Param1Value, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
<TextBlock Text="Param 2 name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding Param2Value, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
...
<TextBlock Text="Param N name" Margin="6,6,0,0"></TextBlock>
<TextBox Text="{Binding ParamNValue, UpdateSourceTrigger=PropertyChanged}" Margin="6,6,0,0"></TextBox>
How can be optimized this code to prevent copy-paste?
Control, Style, ContentControl or DataTemplate?
I can use Style to reuse margin, but how can be reused structure of this pairs TexBlock and TextBox?
Make a UserControl with two properties (E.g., Caption and Text) and bind the TextBlock to the Caption and the TextBox to the Text property.
You could also use a Templated Control if you want to allow the designer to create a custom templates so he can fully control the UI design.
UserControl vs. Custom/Templated Control (read the entire thread for maximum benefit):
Well the difference between user control and custom control is that If
you have a portion of views or UI which will be used repeatedly in
your own project, using UserControl is a much simpler and preferred
way, but if you have a portion of UI and functionality which you
believe will be used aross different projects, then using custom
control is the right approach.
May be you should try an ItemsControl Class and set it's DataTemplate.

WPF: How to embed button inside text flow (wrap text around button)?

I'd like an advice to the following problem: I want to embed a Button into a text flow, but when I embed a Button and Label (or TextBlock) into the WrapPanel, I get the first figure:
alt text http://sklad.tomaskafka.com/files/wpf-wrappanel-problem.png
I think that one of solutions could be FlowDocument, but I feel that this is far too heavy for a control simple like this (which could be used in several hundred instances). Do you have some other ideas about how to implement this? Thank you!
EDIT:
One solution could be the following (I didn't know it was possible to put more stuff into TextBlock), but I would lose the ability to bind (which I need):
<TextBlock TextWrapping="Wrap">
<Span>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<Run x:Name="MyLabel" Text="{Binding Path=Subject}" />
<!--
Problem: binding makes following error:
A 'Binding' cannot be set on the 'Text' property of type 'Run'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
-->
</Span>
</TextBlock>
To bind to Run.Text, checkout the BindableRun class by Fortes. Simple to implement, I use it all over my projects.
I found that implementing BindableRun correctly is pretty tricky - and almost all other available implementations will cause an exception from wpf layouting engine when the bound content changes from null to something non-null - see this problem, keyword "Collection was modified; enumeration operation may not execute."
Corrrect implementation from Microsoft is here - it shows how tricky this really is.
Solution: BindableRun class + the following markup:
<TextBlock>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<common:BindableRun x:Name="Subject" BindableText="{Binding Path=Subject}"/>
</TextBlock>
Funny thing it works on the designer of a UserControl...
In that case, using the Property Change of your control to set the value to the Run is enough. I mean, if you had something like:
<TextBlock>
<Run Text="{Binding ElementName=thisCtrl, Path=Description}" />
</TextBlock>
Then just name the run, and on your property change handler of your UserControl DependencyProperty get/set the value.

Resources