Reputation: 950
I am using a DataGrid
to display some information.
I would like to have a Annotated ScrollBar
for this DataGrid
(to highlight lines, like in VS)
I have this ControlTemplate
in my App.xaml. I added a rectangle in "AnnotationCanvas" as an example, but the idea is to fill this canvas automatically.
However, I can't get a reference to this canvas.
I tried dataGrid.FindName("AnnotationCanvas")
and dataGrid.FindResource("AnnotationCanvas")
, but with no success.
How could I do this ? Thanks in advance.
<ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="18" />
<RowDefinition Height="0.00001*" />
<RowDefinition MaxHeight="18" />
</Grid.RowDefinitions>
<Border Grid.RowSpan="3"
CornerRadius="2"
Background="#F0F0F0" />
<Canvas x:Name="AnnotationCanvas"
Grid.Row="1">
<!--ANNOTATIONS GO HERE-->
<Rectangle Width="3"
Height="30"
Fill="Red" />
</Canvas>
<RepeatButton Grid.Row="0"
Style="{StaticResource ScrollBarLineButton}"
Height="18"
Command="ScrollBar.LineUpCommand"
Content="M 0 4 L 8 4 L 4 0 Z" />
<Track Name="PART_Track"
Grid.Row="1"
IsDirectionReversed="true">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageUpCommand" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"
Margin="1,0,1,0"
Background="{StaticResource HorizontalNormalBrush}"
BorderBrush="{StaticResource HorizontalNormalBorderBrush}" />
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageDownCommand" />
</Track.IncreaseRepeatButton>
</Track>
<RepeatButton Grid.Row="3"
Style="{StaticResource ScrollBarLineButton}"
Height="18"
Command="ScrollBar.LineDownCommand"
Content="M 0 0 L 4 4 L 8 0 Z" />
</Grid>
</ControlTemplate>
Upvotes: 4
Views: 831
Reputation: 950
I found out that the VisualTreeHelper I was using to get to the ScrollBar from the DataGrid won't work it the Control is not completely loaded. InitializeComponent() was not enough, I had to wait for Loaded event to trigger.
Here is my code (working) :
private Canvas annotationCanvas;
private void Loaded(object sender, RoutedEventArgs e) {
ScrollBar scrollBar = GetVisualChild<ScrollBar>(table);
annotationCanvas = (Canvas)scrollBar.Template.FindName("AnnotationCanvas", scrollBar);
UpdateAnnotations();
}
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual {
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++) {
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null) {
child = GetVisualChild<T>(v);
}
if (child != null) {
break;
}
}
return child;
}
// Fill the Canvas with horizontal markers. Can be optimized.
private void UpdateAnnotations() {
if (annotationCanvas == null)
return;
annotationCanvas.Children.Clear();
int i = 0;
double m = items.Count;
double height = table.ActualHeight;
foreach (Item item in items) {
if (item.someCondition) {
int p = (int)(height * i / m);
annotationCanvas.Children.Add(new Line() { X1 = 0, Y1 = p, X2 = 30, Y2 = p, StrokeThickness = 1, Stroke = Brushes.Red });
}
i++;
}
}
Upvotes: 3