Приложение
Я создаю приложение, которое включает селектор диапазона. Он состоит из двух настраиваемых элементов управления Slider, содержащихся в одном классе UserControl. Управление селектором диапазона затем содержится внутри ScrollViewer, в котором видна HorizonalScrollBar, видимая большую часть времени.
Пример кода приложения: (приложения для стены текста)
Window.xaml(файл окна):
<Grid>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
<local:SliderTest x:Name="slider"
LowerValue="0"
UpperValue="10"
Minimum="0"
Maximum="100" Width="900" Height="165" Padding="15,0,15,0" HorizontalAlignment="Left">
</local:SliderTest>
</ScrollViewer>
</Grid>
SliderTest.xaml:
<UserControl x:Class="scrollviewerDemoProblem.SliderTest"
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"
x:Name="root"
xmlns:local="clr-namespace:scrollviewerDemoProblem"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ControlTemplate x:Key="simpleSlider" TargetType="{x:Type Slider}">
<Border SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Track x:Name="PART_Track" Grid.Row="1">
<Track.Thumb>
<Thumb x:Name="Thumb" FlowDirection="LeftToRight" Width="15">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Canvas>
<Path x:Name="test1" StrokeThickness="0" Fill="DarkGreen">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<PathGeometry>
<PathGeometry.Figures>
<PathFigure IsClosed="True" StartPoint="0,150" IsFilled="True">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="-15,150" />
<LineSegment Point="-15,0" />
<LineSegment Point="0,0" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="simpleSliderRight" TargetType="{x:Type Slider}">
<Border SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Track x:Name="PART_Track" Grid.Row="1">
<Track.Thumb>
<Thumb x:Name="Thumb" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Width="15">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Canvas>
<Path Stroke="Black" StrokeThickness="0" Fill="DarkCyan">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<PathGeometry>
<PathGeometry.Figures>
<PathFigure IsClosed="True" StartPoint="0,150">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="15,150" />
<LineSegment Point="15,0" />
<LineSegment Point="0,0" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid x:Name="Gridd" VerticalAlignment="Top" Height="165" >
<Border x:Name="timeScaleBorder" Width="auto" Height="15" VerticalAlignment="Top" Background="Black">
<Canvas x:Name="timeCanvas" Width="auto" Height="15">
</Canvas>
</Border>
<Border x:Name="background" BorderThickness="1,1,1,1" BorderBrush="Black" VerticalAlignment="Center" Height="150"
Margin="0,15,0,0" Background="White" />
<Slider x:Name="LowerSlider"
Minimum="{Binding ElementName=root, Path=Minimum}"
Maximum="{Binding ElementName=root, Path=Maximum}"
Value="{Binding ElementName=root, Path=LowerValue, Mode=TwoWay}"
Template="{StaticResource simpleSlider}"
Margin="0,15,0,0" />
<Slider x:Name="UpperSlider"
Minimum="{Binding ElementName=root, Path=Minimum}"
Maximum="{Binding ElementName=root, Path=Maximum}"
Value="{Binding ElementName=root, Path=UpperValue, Mode=TwoWay}"
Template="{StaticResource simpleSliderRight}"
Margin="0,15,0,0" />
</Grid>
</UserControl>
SliderText.xaml.cs:
public partial class SliderTest : UserControl
{
public SliderTest()
{
InitializeComponent();
}
#region Dependency properties, values etc.
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(SliderTest), new UIPropertyMetadata(0d));
public double LowerValue
{
get { return (double)GetValue(LowerValueProperty); }
set { SetValue(LowerValueProperty, value); }
}
public static readonly DependencyProperty LowerValueProperty =
DependencyProperty.Register("LowerValue", typeof(double), typeof(SliderTest), new UIPropertyMetadata(0d));
public double UpperValue
{
get { return (double)GetValue(UpperValueProperty); }
set { SetValue(UpperValueProperty, value); }
}
public static readonly DependencyProperty UpperValueProperty =
DependencyProperty.Register("UpperValue", typeof(double), typeof(SliderTest), new UIPropertyMetadata(0d));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(SliderTest), new UIPropertyMetadata(1d));
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
#endregion
}
Проблема
Большая часть предоставленного примера кода скучна, и механика этого работает очень хорошо. Проблема, с которой я столкнулась, - это визуальная проблема с элементом управления ScrollViewer, который у меня есть в главном окне. Кажется, что ScrollViewer автоматически корректирует горизонтальное смещение ScrollViewer, когда любой из фокусов (t20) получает фокус (например, с помощью мыши).
Воспроизведение поведения
- Запустите приложение, вы увидите, что горизонтальная полоса прокрутки ScrollViewer видна.
- Нажмите зеленый (крайний левый)
Slider, вы заметите, что ScrollViewer автоматически настраивает смещение горизонтального смещения туда, где начинается воспринимаемое "содержимое".
Эти симптомы появляются на обоих концах панели прокрутки.
Снимок экрана приложения при его запуске (приложение увеличено на 200% для детальной четкости):

Снимок экрана, когда щелкнут левый слайдер:

Что я хочу:
Когда я нажимаю на элемент слайдера (с обоих концов), когда ползунок выглядит за пределами ползунка (диапазон ползунка обозначается черной полосой вверху), я не хочу, чтобы ScrollViewer автоматически настраивал его горизонтальное смещение.
Предполагаемая проблема:
Я подозреваю, что проблема заключается в том, что ScrollViewer воспринимает фактическое "содержимое" этого дочернего элемента начинается с 15 пикселей (рисованная ширина обоих моих ползунков), с которых начинается фактическое рисованное содержимое. Canvas только рисует, потому что я включил прописку из 15 пикселей внутри элемента управления SliderTest в главном окне, если это дополнение удалено, ScrollViewer не отображает ни одного холста слайдера.
РЕДАКТИРОВАТЬ: кажется, что заполнение не является проблемой, прочитайте комментарии о том, почему.
Вещи, которые я пробовал
Я попытался взглянуть на переопределение события OnPreviewMouseDown главного окна. Проблема здесь в том, что я все еще хочу, чтобы Slider вел себя нормально, установив событие в Handled, заставит Slider полностью прекратить работу.
Примечания:
Ползунок в элементе управления селектором диапазона (Called SliderTest в этом примере) должен иметь ширину 1 пиксель. Ползунок должен иметь возможность продлить 15 пикселей за конец диапазона выбора времени (см. Черную полосу вверху для справки).
Спасибо, что прочитали эту проблему с новыми проблемами.