繁体   English   中英

我可以从内部禁用scrollviewer吗?

[英]Can i disable scrollviewer from within?

我有一个ListBox,但我无法修复标题,因此它不会与页面的其余部分一起滚动。 搜索原因后,我发现在通过ContentControl放置所有内容的主窗口中,有一个ScrollViewer包裹着所有内容:

<ScrollViewer Margin="0,0,0,0" >   
    <ContentControl x:Name="content" Margin="0,0,0,0"/>
</ScrollViewer>

我无法真正删除它,因为我只在一个内容页面上工作,该页面稍后将在该项目中实现。 是否可以从我的窗口中禁用此ScrollViewer? 还是以某种方式使其不再影响我的内容?

编辑:要明确。 这段代码(上面)在MainWindow中,我无法编辑。 内容通过content.Content = new (content class)在.cs中添加。 在我正在研究的其中一门课程中,我有:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="20" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="1" Orientation="Horizontal">
        <TextBlock Text ={x:Static ...}>
        <Text Block ...>
    </StackPanel>           

    <ScrollViewer Grid.Row="2">
        <ListBox>...</ListBox>
    </ScrollViewer>
</Grid>

问题是,这个scrollviewer不能正常工作,因为有一个包装在更高的层次上,我无法获得……

也许您可以通过周围ScrollViewer没有理由提供滚动的方式来调整内容的大小。 而是通过限制列表框的高度来滚动列表框:

<!-- When the StackPanel is not bigger than the ScrollViewer, there should be no reason for it to scroll your title out of sight. If there is Padding in your scroll viewer, an additional converter may bre required to modify the height accordingly -->
<StackPanel Height="{Binding ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}}">
    <TextBlock Text="TitleForMyListBox"/>
    <ListBox Height="50">
        <!-- ... -->
    </ListBox>
</StackPanel>

我用50作为高度。 当然,应将其替换为所需的高度。 如果您希望它是动态的,则可以对StackPanelTextBlockActualHeight使用Multibinding ,并使用返回( StackPanel ActualHeight )-( TextBlock ActualHeight )的转换器。

编辑:将其应用于您编辑中的代码:

<Grid Height="{Binding ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}}">
    <Grid.RowDefinitions>
        <RowDefinition Height="20" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <TextBlock Text ={x:Static ...}>
        <Text Block ...>
    </StackPanel>           

    <ListBox Grid.Row="1">...</ListBox>
</Grid>

我有:

  • 固定Grid.Row数字
  • 删除了ScrollViewer因为ListBox将在其高度受到限制时提供滚动
  • ListBox的高度限制为50。同样,应将其替换为所需的高度。 如果希望它是动态的,则可以对GridStackPanelActualHeight进行Multibinding ,并使用返回( Grid ActualHeight )-( StackPanel ActualHeight )的转换器。
  • 添加了Grid HeightBinding

由于我找不到执行此操作的方法,因此我建议使用此AttachedProperty 您可以使用此AttachedProperty禁用ParentView ScrollViewer 。这是实现要求的一种方法。

 public class ScrollViewerExtension : DependencyObject
{

    public static bool GetDisableParentScrollViewer(DependencyObject obj)
    {
        return (bool)obj.GetValue(DisableParentScrollViewerProperty);
    }

    public static void SetDisableParentScrollViewer(DependencyObject obj, bool value)
    {
        obj.SetValue(DisableParentScrollViewerProperty, value);
    }

    // Using a DependencyProperty as the backing store for DisableParentScrollViewer.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DisableParentScrollViewerProperty =
        DependencyProperty.RegisterAttached("DisableParentScrollViewer", typeof(bool), typeof(ScrollViewerExtension), new PropertyMetadata(false,OnDisableParentScrollViewerChanged));

    private static void OnDisableParentScrollViewerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement)
        {
            (d as FrameworkElement).Loaded += (_, __) =>
              {
                  var scrollViewer = FindAncestor(d as Visual, typeof(ScrollViewer)) as ScrollViewer;
                  if (scrollViewer != null && (bool)e.NewValue)
                      scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
              };
        }
    }

    public static Visual FindAncestor(Visual startingFrom, Type typeAncestor)
    {
        if (startingFrom != null)
        {
            DependencyObject parent = VisualTreeHelper.GetParent(startingFrom);

            while (parent != null && !typeAncestor.IsInstanceOfType(parent))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }

            return parent as Visual;
        }

        return null;
    }
}

在您看来,

<Grid attached:ScrollViewerExtension.DisableParentScrollViewer="True">
<Grid.RowDefinitions>
    <RowDefinition Height="20" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Orientation="Horizontal">
    <TextBlock Text ={x:Static ...}>
    <Text Block ...>
</StackPanel>           

<ScrollViewer Grid.Row="2">
    <ListBox>...</ListBox>
</ScrollViewer>

是否可以从我的窗口中禁用此ScrollViewer? 还是以某种方式使其不再影响我的内容?

您可以处理控件的Loaded事件,在视觉树中找到父级ScrollViewer并使用ScrollViewer.SetVerticalScrollBarVisibility方法禁用它。

Window.xaml:

<Window x:Class="WpfApplication1.Window14"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="Window14" Height="300" Width="300">
    <Grid>
        <ScrollViewer Margin="0,0,0,0" Height="200" >
            <ContentControl x:Name="content" Margin="0,0,0,0">
                <ContentControl.Content>
                    <local:UserControl1 />
                </ContentControl.Content>
            </ContentControl>
        </ScrollViewer>
    </Grid>
</Window>

UserControl1.xaml:

<UserControl x:Class="WpfApplication1.UserControl2"
             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" 
             xmlns:local="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Background="Yellow" ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Rectangle Height="100" Fill="Green" />
        <ListBox x:Name="lv" Grid.Row="1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

UserControl1.xaml.cs:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        this.Loaded += UserControl1_Loaded;
        lv.ItemsSource = Enumerable.Range(0, 1000);
    }

    private void UserControl1_Loaded(object sender, RoutedEventArgs e)
    {
        ScrollViewer sv = FindParent<ScrollViewer>(this);
        if (sv != null)
        {
            ScrollViewer.SetVerticalScrollBarVisibility(sv, ScrollBarVisibility.Disabled);
        }
    }

    private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
    {
        var parent = VisualTreeHelper.GetParent(dependencyObject);

        if (parent == null) return null;

        var parentT = parent as T;
        return parentT ?? FindParent<T>(parent);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM