Wpf отключить повторные кнопки при прокрутке вверх / вниз

Я делаю интерфейс с сенсорным экраном, который использует список.
У меня есть кнопка над и под списком для страницы вверх / вниз.

Я пытаюсь получить его там, где при прокрутке до конца кнопка подкачки отключается.
и когда прокручивается полностью вниз, кнопка pagedown тоже отключается.

Вот код в моем Styles.xaml для списка

<Style x:Key="{x:Type ListBox}" TargetType="{x:Type ListBox}">  
    <Setter Property="Template">  
        <Setter.Value>  
            <ControlTemplate x:Key="{x:Type ListBox}" TargetType="{x:Type ListBox}">  
                <DockPanel>  
                    <RepeatButton x:Name="LineUpButton" DockPanel.Dock="Top"  
                        HorizontalAlignment="Stretch"   
                        Height="50"  
                        Content="/\"  
                        Command="{x:Static ScrollBar.PageUpCommand}"  
                        CommandTarget="{Binding ElementName=scrollviewer}" />    
                    <RepeatButton x:Name="LineDownButton" DockPanel.Dock="Bottom"  
                        HorizontalAlignment="Stretch"  
                        Height="50"  
                        Content="\/"  
                        Command="{x:Static ScrollBar.PageDownCommand}"  
                        CommandTarget="{Binding ElementName=scrollviewer}" />  
                    <Border BorderThickness="1" BorderBrush="Gray" Background="White">    
                        <ScrollViewer x:Name="scrollviewer">  
                            <ItemsPresenter/>  
                        </ScrollViewer>  
                    </Border>  
                </DockPanel>  
            </ControlTemplate>  
        </Setter.Value>  
    </Setter>  
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>  
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>  
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />  
</Style> 

И вот где я создаю экземпляр списка

<ListBox SelectedItem="{Binding SelectedCan}" ItemsSource="{Binding Path=SelectedKioskCashCans}">  
    <ListBox.ItemTemplate>  
        <DataTemplate>  
            <ContentPresenter Content="{Binding image}" MaxWidth="75" />  
        </DataTemplate>  
     </ListBox.ItemTemplate>  
     <ListBox.ItemsPanel>  
         <ItemsPanelTemplate>  
             <VirtualizingStackPanel Orientation="Vertical"/>  
         </ItemsPanelTemplate>  
     </ListBox.ItemsPanel>  
</ListBox> 

Я искал вокруг вчера без удачи.
Я надеюсь, что смогу сделать все это в xaml.

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

<RepeatButton x:Name="LineUpButton" DockPanel.Dock="Top" HorizontalAlignment="Stretch" 
    Height="50"      
    Command="{x:Static ScrollBar.PageUpCommand}"      
    CommandTarget="{Binding ElementName=scrollviewer}">
        <RepeatButton.Template>
             <ControlTemplate TargetType="{x:Type RepeatButton}">
                 <Grid>
                     <Image Name="Normal" Source="/Images/up.png"/>
                     <Image Name="Pressed" Source="/Images/up.png" Visibility="Hidden"/>
                 </Grid>
                 <ControlTemplate.Triggers>
                      <Trigger Property="IsPressed" Value="True">
                          <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                          <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
                      </Trigger>
                  </ControlTemplate.Triggers>
             </ControlTemplate>
        </RepeatButton.Template>
   </RepeatButton>

1 ответ

Просто используйте CanExecute метод PageUpCommand для этого. Вернуть false если там не осталось страниц и кнопка автоматически отключится.

РЕДАКТИРОВАТЬ:

Я создал простое прикрепленное поведение, которое можно использовать для решения этой проблемы. Просто установите следующее прикрепленное свойство на ScrollViewer:

<ScrollViewer x:Name="scrollviewer"
              z:ScrollBarCommandsCanExecuteFixBehavior.IsEnabled="True">  
     <ItemsPresenter/>  
</ScrollViewer> 

А вот и исходный код поведения:

public static class ScrollBarCommandsCanExecuteFixBehavior
{
    #region Nested Types

    public class CommandCanExecuteMonitor<T> where T : UIElement
    {
        protected T Target { get; private set; }

        protected CommandCanExecuteMonitor(T target, RoutedCommand command)
        {
            Target = target;

            var binding = new CommandBinding(command);

            binding.CanExecute += OnCanExecute;

            target.CommandBindings.Add(binding);
        }

        protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

        }
    }

    public class PageUpCanExecuteMonitor : CommandCanExecuteMonitor<ScrollViewer>
    {
        public PageUpCanExecuteMonitor(ScrollViewer scrollViewer)
            : base(scrollViewer, ScrollBar.PageUpCommand)
        {
        }

        protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Handled)
            {
                return;
            }

            if (Equals(Target.VerticalOffset, 0.0))
            {
                e.CanExecute = false;
                e.Handled = true;
            }
        }
    }

    public class PageDownCanExecuteMonitor : CommandCanExecuteMonitor<ScrollViewer>
    {
        public PageDownCanExecuteMonitor(ScrollViewer scrollViewer)
            : base(scrollViewer, ScrollBar.PageDownCommand)
        {
        }

        protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Handled)
            {
                return;
            }

            if (Equals(Target.VerticalOffset, Target.ScrollableHeight))
            {
                e.CanExecute = false;
                e.Handled = true;
            }
        }
    }

    #endregion

    #region IsEnabled Attached Property

    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool) obj.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof (bool), typeof (ScrollBarCommandsCanExecuteFixBehavior), new PropertyMetadata(false, OnIsEnabledChanged));

    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool) e.NewValue)
        {
            var scrollViewer = d as ScrollViewer;

            if (scrollViewer != null)
            {
                OnAttached(scrollViewer);
            }
            else
            {
                throw new NotSupportedException("This behavior only supports ScrollViewer instances.");
            }
        }
    }

    private static void OnAttached(ScrollViewer target)
    {
        SetPageUpCanExecuteMonitor(target, new PageUpCanExecuteMonitor(target));
        SetPageDownCanExecuteMonitor(target, new PageDownCanExecuteMonitor(target));
    }

    #endregion

    #region PageUpCanExecuteMonitor Attached Property

    private static void SetPageUpCanExecuteMonitor(DependencyObject obj, PageUpCanExecuteMonitor value)
    {
        obj.SetValue(PageUpCanExecuteMonitorProperty, value);
    }

    private static readonly DependencyProperty PageUpCanExecuteMonitorProperty =
        DependencyProperty.RegisterAttached("PageUpCanExecuteMonitor", typeof (PageUpCanExecuteMonitor), typeof (ScrollBarCommandsCanExecuteFixBehavior), new PropertyMetadata(null));

    #endregion

    #region PageDownCanExecuteMonitor Attached Property

    private static void SetPageDownCanExecuteMonitor(DependencyObject obj, PageDownCanExecuteMonitor value)
    {
        obj.SetValue(PageDownCanExecuteMonitorProperty, value);
    }

    private static readonly DependencyProperty PageDownCanExecuteMonitorProperty =
        DependencyProperty.RegisterAttached("PageDownCanExecuteMonitor", typeof (PageDownCanExecuteMonitor), typeof (ScrollBarCommandsCanExecuteFixBehavior), new PropertyMetadata(null));

    #endregion
}

Основная идея заключается в том, что мы добавляем CommandBinding к ScrollViewer для каждой из команд и подписаться на CanExecute событие на этих привязках. В обработчике событий мы проверяем текущую позицию прокрутки и устанавливаем e.CanExecute собственность соответственно.

Другие вопросы по тегам