WPF在滚动到顶部/底部时禁用重复按钮 [英] Wpf disable repeatbuttons when scrolled to top/bottom

查看:77
本文介绍了WPF在滚动到顶部/底部时禁用重复按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个使用列表框的触摸屏界面.
我在列表框的上方和下方都有一个按钮,用于上/下翻页.

I'm making a touchscreen interface that uses a listbox.
I have a button above and below the listbox for page up/down.

我试图将其一直滚动到上一页按钮禁用的位置.
并一直向下滚动时,向下翻页按钮也将被禁用.

I'm trying to get it to where when scrolled all the way up the pageup button gets disabled.
and when scrolled all the way down the pagedown button gets disabled too.

这是我的Styles.xaml中用于列表框的代码

Here's the code in my Styles.xaml for the Listbox

<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> 

这是我实例化列表框的地方

And here's where I instantiate the listbox

<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中完成所有操作.

I searched all around yesterday with no luck.
I'm hoping to be able to do it all in xaml.

我在按钮上使用图像,但出于可读性考虑将其取出,
他们真的看起来像...

I'm using images for the buttons but took them out for readability above,
they really look like...

<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>

推荐答案

为此只需使用PageUpCommandCanExecute方法.如果没有剩余页面,则返回false,该按钮将自动被禁用.

Just use CanExecute method of the PageUpCommand for that. Return false if where are no pages left and the button will become disabled automatically.

我创建了一个简单的附加行为可用于解决此问题.只需在ScrollViewer上设置以下附加属性:

I have created a simple attached behavior that can be used to fix this problem. Just set the following attached property on the 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属性.

The basic idea is that we add a CommandBinding to the ScrollViewer for each of the commands and subscribe to the CanExecute event on those bindings. In the event handler we check the current position of the scroll and set the e.CanExecute property accordingly.

这篇关于WPF在滚动到顶部/底部时禁用重复按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆