2016-12-22 4 views
2

Touch:Из кода: scrollbars' стиль изменить ScrollViewer к потрогать

enter image description here

Мышь:

enter image description here

Как сказать ScrollViewer начать использовать скроллбар сенсорный стиль от кода?

Вот пример:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <ScrollViewer Name="scrollViewer1" HorizontalScrollBarVisibility="Visible" > 
     <Image Stretch="UniformToFill"> 
      <Image.Source> 
       <BitmapImage x:Name="bitmapImage1" UriSource="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png"></BitmapImage> 
      </Image.Source> 
     </Image> 
    </ScrollViewer> 
</Grid> 

И:

public sealed partial class MainPage : Page 
{ 
    DispatcherTimer dispatcherTimer1 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) }; 
    bool SE; 

    public MainPage() 
    { 
     this.InitializeComponent(); 
     dispatcherTimer1.Tick += DispatcherTimer1_Tick; 
     dispatcherTimer1.Start(); 
    } 

    private void DispatcherTimer1_Tick(object sender, object e) 
    { 
     if (SE = !SE) bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/se/se-icon.png"); 
     else bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png"); 
     scrollViewer1.ChangeView(SE ? 1 : 0, SE ? 1 : 0, null); 
    } 
} 

Если запустить этот (по крайней мере, на включенном компьютере Соприкосновение) скроллбары первоначально будет прикосновение. И если вы переместите курсор над ним с помощью мыши, он изменится на мышь. и если вы затем коснетесь его (после того, как полосы прокрутки были скрыты), он вернется к касанию.

Я хочу сказать это программно, чтобы перейти от одного к другому. Как это можно сделать? Если единственным способом является редактирование шаблона - как это можно сделать без жесткое кодирование the template? Просто фиксируйте детали, требующие исправления. Чтобы быть ясным: я хочу иметь возможность вызвать метод, который будет меняться от одного к другому: void ChangeTo(bool mouse) { ... }. (Хотя, если это невозможно, просто заставляя ScrollViewer, чтобы всегда быть в одном режиме, будет несколько обходной путь.)

ответ

1

в шаблоне по умолчанию есть 3 VisualStates определены: NoIndicator, TouchIndicator и MouseIndicator

Стиль скроллера большого пальца выглядит в зависимости от того, какое состояние в данный момент установлено. Для изменения управления утверждают, вы можете вызвать

VisualStateManager.GoToState(scrollViewer1, "TouchIndicator"); 

но вы должны вручную заботиться обо всех событиях и действиях, когда это состояние может измениться.

Но если вы хотите, чтобы всегда TouchIndicator видимую то лучшее решение, на мой взгляд было бы реализовать CustomVisualStateManager, например:

public class MyVisualStateManager : VisualStateManager 
{ 
    protected override bool GoToStateCore(Control control, FrameworkElement templateRoot, 
     System.String stateName, VisualStateGroup group, VisualState state, System.Boolean useTransitions) 
    { 
     switch (stateName) 
     { 
      case "NoIndicator": 
      case "TouchIndicator": 
      case "MouseIndicator": 
       base.GoToStateCore(control, templateRoot, "TouchIndicator", group, state, useTransitions); 
       break; 
     } 
     return true; 
    } 
} 

Затем необходимо скопировать шаблон из MSDN, установите его в ScrollViewer и поставить MyVisualStateManager в нем:

<Style TargetType="ScrollViewer" x:Key="ScrollStyle"> 
     <Setter Property="HorizontalScrollMode" Value="Auto" /> 
     <Setter Property="VerticalScrollMode" Value="Auto" /> 
     <Setter Property="IsHorizontalRailEnabled" Value="True" /> 
     <Setter Property="IsVerticalRailEnabled" Value="True" /> 
     <Setter Property="IsTabStop" Value="False" /> 
     <Setter Property="ZoomMode" Value="Disabled" /> 
     <Setter Property="HorizontalContentAlignment" Value="Left" /> 
     <Setter Property="VerticalContentAlignment" Value="Top" /> 
     <Setter Property="VerticalScrollBarVisibility" Value="Visible" /> 
     <Setter Property="Padding" Value="0" /> 
     <Setter Property="BorderThickness" Value="0" /> 
     <Setter Property="BorderBrush" Value="Transparent" /> 
     <Setter Property="Background" Value="Transparent" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="ScrollViewer"> 
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
         <VisualStateManager.CustomVisualStateManager> 
          <local:MyVisualStateManager/> 
         </VisualStateManager.CustomVisualStateManager> 
         <VisualStateManager.VisualStateGroups> 
          <VisualStateGroup x:Name="ScrollingIndicatorStates"> 
           <VisualStateGroup.Transitions> 
            <VisualTransition From="MouseIndicator" To="NoIndicator"> 
             <Storyboard> 
           (... blabla ...) 
</Style> 

набор стилей:

<ScrollViewer Name="scrollViewer1" Style="{StaticResource ScrollStyle}" HorizontalScrollBarVisibility="Visible"> 

Теперь, когда ваше состояние ScrollViewer необходимо изменить, вы игнорируете точное состояние, которое требуется, вместо этого установите TouchIndicator.

+0

Спасибо! Кажется, это так. Хотя я не понимал, что вы подразумеваете под «но вам нужно будет вручную позаботиться обо всех событиях и действиях, когда это состояние может измениться». Поскольку я не отменяю подписку на какие-либо события, почему что-то изменится (кроме государство, конечно)? – ispiro

+0

Например, состояние изменения ScrollViewer запускается каждый раз, когда указатель мыши входит и выходит из ScrollViewer (и даже если вы перемещаете мышь внутри, насколько я помню). Поэтому, если вы установите его с помощью VisualStateManager.GoToState (что-то), он будет изменен и настроен на IndicatorMouse, если в него будет введен указатель мыши. Кажется, спорить с системой о том, какое состояние должно быть установлено (мой мой мой!). Использование CustomiVisualStateManager лучше - это способ, которым вы обрезаете систему так, как вы решаете, когда и какое состояние должно быть установлено. – RTDev

2

Windows, имеет два скроллера визуализации, основанные на режиме ввода пользователя: индикаторы прокрутки при использовании сенсорный или геймпад; и интерактивные полосы прокрутки для других устройств ввода, включая мышь, клавиатуру и ручку.

enter image description here

А в Guidelines for panning, заявлено, что

Есть два панорамирование режима отображения на основании входного устройства обнаружены:

  • Панорамирование индикаторы для прикосновения.
  • Полосы прокрутки для других устройств ввода, включая мышь, тачпад, клавиатуру и стилус.

Примечание индикаторы Мытье видны только, когда сенсорный контакт находится в пределах pannable области. Аналогично, полоса прокрутки видна только тогда, когда курсор мыши, курсор пера/стилуса или фокус клавиатуры находятся в зоне прокрутки.

Индикаторы панорамирования Индикаторы панорамирования аналогичны шкале прокрутки в полосе прокрутки. Они показывают долю отображаемого содержимого в общей площади подкачки и относительное положение отображаемого содержимого в области подкачки.

Примечание В отличие от стандартных полос прокрутки индикаторы панорамирования являются чисто информативными. Они не подвержены входным устройствам и не могут быть обработаны каким-либо образом.

Таким образом, режим отображения основан на пользовательском режиме ввода, мы не можем программно изменить его из одного в другое. Мы можем сделать редактирование ScrollViewer's template, чтобы ScrollViewer использовал только один интерфейс визуализации.

В стиле по умолчанию, можно найти ScrollViewer три VisualState S: NoIndicator, TouchIndicator и MouseIndicator, которые используются для управления режимом отображения. Мы можем изменить TouchIndicator или MouseIndicator визуальное состояние, чтобы сделать ScrollViewer всегда в одном режиме.

Например, мы можем заменить Storyboard под «TouchIndicator» VisualState с Storyboard под «MouseIndicator» VisualState сделать ScrollViewer всегда в режиме прокрутки бар, как:

<ControlTemplate x:Key="MouseIndicatorTemplate" TargetType="ScrollViewer"> 
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="ScrollingIndicatorStates"> 
       <VisualStateGroup.Transitions> 
        <VisualTransition From="MouseIndicator" To="NoIndicator"> 
         <Storyboard> 
          <FadeOutThemeAnimation BeginTime="0:0:3" TargetName="ScrollBarSeparator" /> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:3"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:3"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
         </Storyboard> 
        </VisualTransition> 
        <VisualTransition From="TouchIndicator" To="NoIndicator"> 
         <Storyboard> 
          <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
         </Storyboard> 
        </VisualTransition> 
       </VisualStateGroup.Transitions> 
       <VisualState x:Name="NoIndicator"> 
        <Storyboard> 
         <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
        </Storyboard> 
       </VisualState> 
       <VisualState x:Name="TouchIndicator"> 
        <Storyboard> 
         <FadeInThemeAnimation TargetName="ScrollBarSeparator" /> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
       <VisualState x:Name="MouseIndicator"> 
        <Storyboard> 
         <FadeInThemeAnimation TargetName="ScrollBarSeparator" /> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <Grid Background="{TemplateBinding Background}"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="Auto" /> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*" /> 
       <RowDefinition Height="Auto" /> 
      </Grid.RowDefinitions> 
      <ScrollContentPresenter x:Name="ScrollContentPresenter" 
            Grid.RowSpan="2" 
            Grid.ColumnSpan="2" 
            Margin="{TemplateBinding Padding}" 
            ContentTemplate="{TemplateBinding ContentTemplate}" /> 
      <Grid Grid.RowSpan="2" Grid.ColumnSpan="2" /> 
      <ScrollBar x:Name="VerticalScrollBar" 
         Grid.Column="1" 
         HorizontalAlignment="Right" 
         IsTabStop="False" 
         Maximum="{TemplateBinding ScrollableHeight}" 
         Orientation="Vertical" 
         ViewportSize="{TemplateBinding ViewportHeight}" 
         Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" 
         Value="{TemplateBinding VerticalOffset}" /> 
      <ScrollBar x:Name="HorizontalScrollBar" 
         Grid.Row="1" 
         IsTabStop="False" 
         Maximum="{TemplateBinding ScrollableWidth}" 
         Orientation="Horizontal" 
         ViewportSize="{TemplateBinding ViewportWidth}" 
         Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" 
         Value="{TemplateBinding HorizontalOffset}" /> 
      <Border x:Name="ScrollBarSeparator" 
        Grid.Row="1" 
        Grid.Column="1" 
        Background="{ThemeResource ScrollViewerScrollBarSeparatorBackground}" /> 
     </Grid> 
    </Border> 
</ControlTemplate> 

И наоборот.

<ControlTemplate x:Key="TouchIndicatorTemplate" TargetType="ScrollViewer"> 
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="ScrollingIndicatorStates"> 
       <VisualStateGroup.Transitions> 
        <VisualTransition From="MouseIndicator" To="NoIndicator"> 
         <Storyboard> 
          <FadeOutThemeAnimation BeginTime="0:0:3" TargetName="ScrollBarSeparator" /> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:3"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:3"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
         </Storyboard> 
        </VisualTransition> 
        <VisualTransition From="TouchIndicator" To="NoIndicator"> 
         <Storyboard> 
          <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode"> 
           <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
            <DiscreteObjectKeyFrame.Value> 
             <ScrollingIndicatorMode>None</ScrollingIndicatorMode> 
            </DiscreteObjectKeyFrame.Value> 
           </DiscreteObjectKeyFrame> 
          </ObjectAnimationUsingKeyFrames> 
         </Storyboard> 
        </VisualTransition> 
       </VisualStateGroup.Transitions> 
       <VisualState x:Name="NoIndicator"> 
        <Storyboard> 
         <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
        </Storyboard> 
       </VisualState> 
       <VisualState x:Name="TouchIndicator"> 
        <Storyboard> 
         <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
       <VisualState x:Name="MouseIndicator"> 
        <Storyboard> 
         <FadeOutThemeAnimation TargetName="ScrollBarSeparator" /> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <Grid Background="{TemplateBinding Background}"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="Auto" /> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*" /> 
       <RowDefinition Height="Auto" /> 
      </Grid.RowDefinitions> 
      <ScrollContentPresenter x:Name="ScrollContentPresenter" 
            Grid.RowSpan="2" 
            Grid.ColumnSpan="2" 
            Margin="{TemplateBinding Padding}" 
            ContentTemplate="{TemplateBinding ContentTemplate}" /> 
      <Grid Grid.RowSpan="2" Grid.ColumnSpan="2" /> 
      <ScrollBar x:Name="VerticalScrollBar" 
         Grid.Column="1" 
         HorizontalAlignment="Right" 
         IsTabStop="False" 
         Maximum="{TemplateBinding ScrollableHeight}" 
         Orientation="Vertical" 
         ViewportSize="{TemplateBinding ViewportHeight}" 
         Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" 
         Value="{TemplateBinding VerticalOffset}" /> 
      <ScrollBar x:Name="HorizontalScrollBar" 
         Grid.Row="1" 
         IsTabStop="False" 
         Maximum="{TemplateBinding ScrollableWidth}" 
         Orientation="Horizontal" 
         ViewportSize="{TemplateBinding ViewportWidth}" 
         Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" 
         Value="{TemplateBinding HorizontalOffset}" /> 
      <Border x:Name="ScrollBarSeparator" 
        Grid.Row="1" 
        Grid.Column="1" 
        Background="{ThemeResource ScrollViewerScrollBarSeparatorBackground}" /> 
     </Grid> 
    </Border> 
</ControlTemplate> 

После того, как у нас есть эти два шаблона, мы можем использовать ScrollViewer.Template свойство для изменения режима отображения от одного к другому, как следующее («MouseIndicatorTemplate» и «TouchIndicatorTemplate» помещены в Page.Resources):

void ChangeTo(bool mouse) 
{ 
    if (mouse) 
    { 
     scrollViewer1.Template = (ControlTemplate)Resources["MouseIndicatorTemplate"]; 
    } 
    else 
    { 
     scrollViewer1.Template = (ControlTemplate)Resources["TouchIndicatorTemplate"]; 
    } 
} 
Смежные вопросы