Я создал слегка настроенную вертикальную полосу прокрутки для своего DataGrid. В нем я добавил ItemsControl для хранения позиций выбранных элементов. Вот макет с жестко запрограммированными маркерами.
Ниже приведен мой настраиваемый шаблон вертикальной полосы прокрутки, где ItemsControl размещен с жестко закодированными значениями маркера.
<ControlTemplate x:Key="VertScrollBar" TargetType="{x:Type ScrollBar}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="18" />
<RowDefinition Height="0.00001*" />
<RowDefinition MaxHeight="18" />
</Grid.RowDefinitions>
<Border Grid.RowSpan="3" CornerRadius="2" Background="#F0F0F0" />
<RepeatButton Grid.Row="0" Style="{StaticResource ScrollBarLineButton}" Height="18" Command="ScrollBar.LineUpCommand" Content="M 0 4 L 8 4 L 4 0 Z" />
<Track x: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">
<Thumb.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.BorderBrush>
<Thumb.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.Background>
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageDownCommand" />
</Track.IncreaseRepeatButton>
</Track>
<!-- BEGIN -->
<ItemsControl Grid.Column="0" VerticalAlignment="Stretch" Name="ItemsSelected">
<sys:Double>30</sys:Double>
<sys:Double>70</sys:Double>
<sys:Double>120</sys:Double>
<sys:Double>170</sys:Double>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="SlateGray" Width="18" Height="4"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Top" Value="{Binding}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!-- END -->
<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>
Далее я пытаюсь создать AttachedProperty для хранения позиций маркеров и привязать его обратно к ItemsControl.
Чего я действительно не понимаю, так это:
– Каким должно быть это прикрепленное свойство Type, ObservableCollection из int?
– Поскольку это руководство по общему количеству выбранных элементов в DataGrid, укажите позиции маркеры нужно как-то масштабировать?
- У меня есть прикрепленное поведение, которое захватывает DataGrid.SelectionChanged, но что, если основная коллекция изменится, и для этого не будет события?
[ИЗМЕНИТЬ]
Для прямой привязки к DataGrids SelectedItems. (Однако в верхней части ItemsControl появляется мерцание, когда что-то выбрано)
– Удалите или закомментируйте поведение SelectionChanged.
– Измените ItemSource на:
ItemsSource="{Binding ElementName=GenericDataGrid, Path=SelectedItems}"
- Измените мультипривязку на:
<MultiBinding Converter="{StaticResource MarkerPositionConverter}">
<Binding/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}" />
<Binding Path="ActualHeight" ElementName="ItemsSelected"/>
<Binding Path="Items.Count" ElementName="GenericDataGrid"/>
</MultiBinding>
- И, наконец, конвертер в:
public class MarkerPositionConverter: IMultiValueConverter
{
//Performs the index to translate conversion
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//calculated the transform values based on the following
object o = (object)values[0];
DataGrid dg = (DataGrid)values[1];
double itemIndex = dg.Items.IndexOf(o);
double trackHeight = (double)values[2];
int itemCount = (int)values[3];
double translateDelta = trackHeight / itemCount;
return itemIndex * translateDelta;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}