I have a viewmodel that has a list GraphConfig objects that I bind to an ItemsControl. I am trying to generate as much as I can from xaml but I have run into serveral areas that I am not able to use straight databinding. One of the first things I ran into is I was trying to bind the xaxis labelsetting visibility to a property on the GraphConfig object. The problem is that no matter what I put in there I always get the same error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Infragistics.Controls.Charts.XamDataChart', AncestorLevel='1''. BindingExpression:Path=DataContext.IsLast; DataItem=null; target element is 'AxisLabelSettings' (HashCode=12116793); target property is 'Visibility' (type 'Visibility')
I thought the below code would work but it didn't. I also replaced this code with other bindings that do work in the same template and still get the same error.
<ig:AxisLabelSettings Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ig:XamDataChart}}, Path=DataContext.IsLast, Converter={StaticResource BooleanToVisibilityConverter}}" Location="OutsideBottom" />
Here is the template:
<ItemsControl ItemsSource="{Binding Graphs}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Vertical"></StackPanel> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <ig:XamDock x:Name="XamDataChartContainer1" Margin="0"> <ig:XamDataChart Margin="0" Height="200" CrosshairVisibility="Visible" CrosshairLineStyle="{StaticResource CrosshairLineStyle}" VerticalZoomable="False" VerticalZoombarVisibility="Collapsed" HorizontalZoomable="False" HorizontalZoombarVisibility="Collapsed" Background="Black" PlotAreaBorderBrush="Black" PlotAreaBackground="Black" BorderThickness="0" PlotAreaBorderThickness="0" Legend="{Binding ElementName=xmLegend}" > <behavior:ChartBehaviors.HoveredScatterItems> <behavior:HoveredScatterItemsBehavior /> </behavior:ChartBehaviors.HoveredScatterItems> <behavior:ChartBehaviors.HoveredCategoryItems> <behavior:HoveredCategoryItemsBehavior CategoryOffset="True"> <behavior:HoveredCategoryItemsBehavior.ItemComparer> <model:CustomDateTimeItemComparer /> </behavior:HoveredCategoryItemsBehavior.ItemComparer> </behavior:HoveredCategoryItemsBehavior> </behavior:ChartBehaviors.HoveredCategoryItems> <behavior:ChartBehaviors.FloatingTooltip> <behavior:FloatingTooltipBehavior TooltipTemplate="{StaticResource tooltipTemplate}" HoveredItems="{Binding Path=(behavior:ChartBehaviors.HoveredCategoryItems).HoveredItems}"/> </behavior:ChartBehaviors.FloatingTooltip> <ig:XamDataChart.Axes> <ig:NumericXAxis x:Name="dateAxis" Visibility="Visible" MinimumValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MinDateTime.Ticks}" MaximumValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MaxDateTime.Ticks}"> <ig:NumericXAxis.Label> <DataTemplate> <TextBlock Text="{Binding Path=Item, Converter={StaticResource TicksToDateTime}, ConverterParameter='HH:mm:ss'}" Foreground="White" /> </DataTemplate> </ig:NumericXAxis.Label> <ig:NumericXAxis.LabelSettings> <ig:AxisLabelSettings Visibility="Collapsed" Location="OutsideBottom" /> </ig:NumericXAxis.LabelSettings> </ig:NumericXAxis> </ig:XamDataChart.Axes> <ig:XamDataChart.Series> </ig:XamDataChart.Series> <ig:SyncManager.SyncSettings> <ig:SyncSettings SyncChannel="syncGroup1" SynchronizeHorizontally="True" SynchronizeVertically="False"/> </ig:SyncManager.SyncSettings> </ig:XamDataChart> <ig:Legend x:Name="xmLegend" ig:XamDock.Edge="InsideTop" ig:XamDock.HorizontalDockAlignment="Left" ig:XamDock.VerticalDockAlignment="Top" Style="{StaticResource LegendStyle}"> </ig:Legend> </ig:XamDock> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
Will I be able to add series in this method?
If I cannot dynamically create xamdatacharts. series and legend by databinding is there a way to replicate all the xaml in codebehind? for example how do I replicate this in code behind?
<ig:Legend x:Name="xmLegend"ig:XamDock.Edge="InsideTop"ig:XamDock.HorizontalDockAlignment="Left"ig:XamDock.VerticalDockAlignment="Top"Style="{StaticResource LegendStyle}"></ig:Legend>
And how do I add the above behaviors to the chart in the codebehind?
I have been able to replicate everything in codebehind now except for the behaviors. Anyone have an idea how to accomplish this in code behind? Here is my AddGraph function:
private void AddGraph(GraphConfig config) { var leftlegend = new Legend { Style = Resources["LegendStyle"] as Style }; var rightlegend = new Legend { Style = Resources["LegendStyle"] as Style };
var dock = new XamDock(); int sizepercent;
var graph = new XamDataChart { Margin = new Thickness(0), Height = (1080 - 200 - SelectionGrid.ActualHeight - 10) * (double.Parse(config.SizePercentage.TrimEnd( new char[] { '%', ' ' })) / 100), //This needs work to make it fluid. Had to assume 1080 for now and subtract off some for the header bar and some for the CrosshairVisibility = Visibility.Visible, CrosshairLineStyle = Resources["CrosshairLineStyle"] as Style, VerticalZoomable = false, VerticalZoombarVisibility = Visibility.Collapsed, HorizontalZoomable = false, HorizontalZoombarVisibility = Visibility.Collapsed, Background = new SolidColorBrush(Colors.Black), PlotAreaBorderBrush = new SolidColorBrush(Colors.Black), PlotAreaBackground = new SolidColorBrush(Colors.Black), BorderThickness = new Thickness(0), PlotAreaBorderThickness = new Thickness(0), Legend = leftlegend }; // Synchronize all the added graphs horizontally SyncManager.SetSyncSettings(graph, new SyncSettings { SyncChannel = "testsync", SynchronizeHorizontally = true, SynchronizeVertically = false });
// TODO: Figure out how to add the hover over items for popups to display the current values //var hoveredScatterItemBehavior = new HoveredScatterItemsBehavior(); //Interaction.GetBehaviors(graph).Add((Behavior)new LiveVue.Behaviors.HoveredScatterItemsBehavior()); var yaxis = new NumericYAxis { LabelSettings = new AxisLabelSettings { Visibility = Visibility.Visible, Location = AxisLabelsLocation.OutsideLeft, Foreground = new SolidColorBrush(Colors.White) }, //Label = null, Style = Resources["NumericYAxisStyle"] as Style, MinimumValue = 0, MaximumValue = 100 }; yaxis.IsInverted = yaxis.MinimumValue > yaxis.MaximumValue; yaxis.Name = String.Format("y_{0}", config.Name.RemoveSpecialCharacters());
var xaxis = new NumericXAxis { LabelSettings = new AxisLabelSettings { Visibility = config.IsLast ? Visibility.Visible : Visibility.Collapsed, // Only show the bottom xaxis labels Location = AxisLabelsLocation.OutsideBottom }, Name = "dateAxis", Label = Resources["NumericXAxisLabelTemplate"] as DataTemplate };
// these bindings ensure that all x axes have the same range xaxis.SetBinding(NumericAxisBase.MinimumValueProperty, new Binding("MinDateTime.Ticks")); xaxis.SetBinding(NumericAxisBase.MaximumValueProperty, new Binding("MaxDateTime.Ticks")); graph.Axes.Add(xaxis); graph.Axes.Add(yaxis);
dock.Children.Add(graph); dock.Children.Add(leftlegend); dock.Children.Add(rightlegend);
// Set the locations of the left and right legends XamDock.SetEdge(leftlegend, DockEdge.InsideTop); XamDock.SetHorizontalDockAlignment(leftlegend, HorizontalAlignment.Left); XamDock.SetEdge(rightlegend, DockEdge.InsideTop); XamDock.SetHorizontalDockAlignment(rightlegend, HorizontalAlignment.Right);
GraphStack.Children.Add(dock); }
Hello Mike,
Thank you for the clarification and the provided sample application. I have been looking into code that you have provided me with and the you can set the HoveredItems property by getting the HoveredCategoryItems for the XamDataChart and then using the its HoveredItems. Here is an example of how you can set the FloatingTooltip:
ChartBehaviors.SetFloatingTooltip(chart, new FloatingTooltipBehavior { HoveredItems = ChartBehaviors.GetHoveredCategoryItems(chart).HoveredItems });
Please let me know if you need any further assistance on the matter.
Sincerely,
Krasimir
Developer Support Engineer
Infragistics
www.infragistics.com/support
The code I have is pretty much what Graham Murray provided about a year ago. I attached the code rather than paste it in because I can't seem to get it to format properly in the text window (and it is rather long). This is the only behavior I have ever used so the code you provided appears to work for everything but the HoveredItems property in the FloatingTooltip behavior.
Basically, the floating tooltip needs to be displayed any time the mouse is over the chart and display the data contained in the HoveredItems collection generated by the HoveredCategoryItems behavior. That collection is defined inside the HoveredCategoryItemsBehavior class so I am still a little uncertain how to access it from codebehind.
Thank you for your posts. I am very glad that you have managed to convert the xaml code to C#. I have been looking into the Behaviors that you are using and I am not completely sure what is their implementation. I assume that setting the ChartBehaviors in code should look as follows:
ChartBehaviors.SetHoveredScatterItems(graph, new HoveredScatterItemsBehavior()); ChartBehaviors.SetHoveredCategoryItems(graph, new HoveredCategoryItemsBehavior { CategoryOffset = true, ItemComparer = new CustomDateTimeItemComparer() }); ChartBehaviors.SetFloatingTooltip(graph, new new FloatingTooltipBehavior { ToolTipTemplate = Resources["tooltipTemplate"] as DataTemplate, HoveredItems = ChartBehaviors.HoveredCategoryItems.HoveredItems });
Would you please, if possible, provide me with the implementation of the ChartBehavoir class, in order to be able to research more accurately, how the xaml code that you are using can be implemented using C# code?
Looking forward to hearing from you.