【问题标题】:Wpf disable repeatbuttons when scrolled to top/bottom滚动到顶部/底部时,Wpf 禁用重复按钮
【发布时间】:2011-01-25 15:07:31
【问题描述】:

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

我正在尝试将其移至一直向上滚动时页面向上按钮被禁用的位置。
并且当一直向下滚动时,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>

【问题讨论】:

    标签: wpf xaml listbox repeatbutton


    【解决方案1】:

    只需使用PageUpCommand 的CanExecute 方法即可。如果没有页面,则返回false,按钮将自动禁用。

    编辑:

    我创建了一个简单的attached behavior 可以用来解决这个问题。只需在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 属性。

    【讨论】:

    • 优秀。完美运行。我不得不禁用 LineLeft 和 LineRight 按钮,并稍作改动,它可以按预期工作。谢谢!
    • 我正在使用此代码来弹出组合框。我尝试将它用于 LineUp 和 LineDown 命令,如果我按原样使用它,当我到达滚动查看器的顶部时,折叠上的弹出窗口会崩溃。如果我注释掉“e.Handled = true”,它不会隐藏,但 canExecute 仍然是 true,因为我的重复按钮没有被禁用。所以这段代码对我不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    相关资源
    最近更新 更多