wpf scrollviewer开始滚动到早期

发布于 2025-02-11 03:46:16 字数 2903 浏览 1 评论 0原文

我需要一种使按钮在水平调整到较小尺寸时重叠文本块的方法。对于第一个示例,这可以正常工作,但是当我将相同的代码放在滚动浏览器中时,水平滚动栏从文本和按钮开始就开始了见面。 如何避免使用此功能,以使该按钮与没有ScrollViewer的情况相同?理想情况下,滚动应从文本块达到其最小宽度的那一刻开始。

      <StackPanel>
            <!--works-->
            <Grid Height="30" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
                <Button Grid.Column="1" MinWidth="20">te</Button>
            </Grid>

            <!--doesn't work-->
            <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
                <Grid Height="30" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
                    <Button Grid.Column="1" MinWidth="20">te</Button>
                </Grid>
            </ScrollViewer>
        </StackPanel>

更新 实际上,我可以将问题减少到滚动浏览器中的文本块。我希望,只有在达到文本块的最小宽度时,水平卷轴才有可能滚动。

    <ScrollViewer HorizontalScrollBarVisibility="Visible" 
                      VerticalScrollBarVisibility="Disabled">
        <TextBlock Background="Yellow" 
                   MinWidth="50">reallylooooooooooooooooooooong 
                   text</TextBlock>
    </ScrollViewer>

更新 I found a solution here

我不知道任何内容的自定义滚动浏览器是否足够聪明,可以以相同的方式行事?

<ScrollViewer HorizontalScrollBarVisibility="Visible" 
            VerticalScrollBarVisibility="Disabled"
            >
    <Grid Height="30" x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  
                HorizontalAlignment="Left"
                MinWidth="150"
                Width="{Binding ElementName=grid, Path=ActualWidth, 
                 Converter={x:Static conv:WidthConverter.Instance}}"
                ></TextBlock>
        <Button Grid.Column="1" MinWidth="20">te</Button>
    </Grid>
</ScrollViewer>

I need a way to make a button overlap a textblock when resizing horizontally to a smaller size.This works fine for the first example, but when i put the same code in a scrollviewer, the horizontal scrollbar kicks in from the moment the textblock and button meet.
How can i avoid this so that the button overlaps the same way as without the scrollviewer? Ideally scrolling should start from the moment that the textblock reaches its minimum width.

      <StackPanel>
            <!--works-->
            <Grid Height="30" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
                <Button Grid.Column="1" MinWidth="20">te</Button>
            </Grid>

            <!--doesn't work-->
            <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
                <Grid Height="30" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
                    <Button Grid.Column="1" MinWidth="20">te</Button>
                </Grid>
            </ScrollViewer>
        </StackPanel>

Update
In fact i can reduce the problem to a textblock in a scrollviewer. I would like that it would only become possible for the horizontal scrollbar to scroll when the min width of the textblock is reached.

    <ScrollViewer HorizontalScrollBarVisibility="Visible" 
                      VerticalScrollBarVisibility="Disabled">
        <TextBlock Background="Yellow" 
                   MinWidth="50">reallylooooooooooooooooooooong 
                   text</TextBlock>
    </ScrollViewer>

Update
I found a solution here https://social.msdn.microsoft.com/Forums/en-US/26e03045-4b57-4960-8d33-d0295855f4e3/minwidth-with-scrollviewer-to-then-take-over?forum=wpf
The converter substracts the width of the button from the actual width of the grid.Now it starts scrolling the moment that the minimum width of the textblock is reached.

I don't know if a custom scrollviewer for any content could be smart enough to behave the same way?

<ScrollViewer HorizontalScrollBarVisibility="Visible" 
            VerticalScrollBarVisibility="Disabled"
            >
    <Grid Height="30" x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  
                HorizontalAlignment="Left"
                MinWidth="150"
                Width="{Binding ElementName=grid, Path=ActualWidth, 
                 Converter={x:Static conv:WidthConverter.Instance}}"
                ></TextBlock>
        <Button Grid.Column="1" MinWidth="20">te</Button>
    </Grid>
</ScrollViewer>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

弥枳 2025-02-18 03:46:16

如果要在面板中显示多个元素,由scrollviewer管辖,可以在itemscontrol scrollviewer内使用itemscontrol

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" >
      <ItemsControl >
        <Grid Height="30">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"
                     HorizontalAlignment="Left"></TextBlock>
          <Button Grid.Column="1"
                  MinWidth="20">te</Button>
        </Grid>
        <Grid Height="30">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"
                     HorizontalAlignment="Left"></TextBlock>
          <Button Grid.Column="1"
                  MinWidth="20">te</Button>
        </Grid>
      </ItemsControl>
    </ScrollViewer>

If you want to show multiple elements in a panel, governed by a scrollviewer you may use an ItemsControl inside the ScrollViewer

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" >
      <ItemsControl >
        <Grid Height="30">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"
                     HorizontalAlignment="Left"></TextBlock>
          <Button Grid.Column="1"
                  MinWidth="20">te</Button>
        </Grid>
        <Grid Height="30">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
          </Grid.ColumnDefinitions>
          <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"
                     HorizontalAlignment="Left"></TextBlock>
          <Button Grid.Column="1"
                  MinWidth="20">te</Button>
        </Grid>
      </ItemsControl>
    </ScrollViewer>
心欲静而疯不止 2025-02-18 03:46:16

您需要重新绘制ScrollViewer控件。首先通过将光标移动到滚动视图控制器和属性窗格中,从而提取模板。模板 - &GT;转换为新资源(从下拉列表)。出现的新模板中的卷轴卷件是绘制“客户端区域”内部所有内容的内容:

<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanHorizontallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" CanVerticallyScroll="False" Grid.Column="0" Content="{TemplateBinding Content}" CanContentScroll="{TemplateBinding CanContentScroll}" Margin="{TemplateBinding Padding}" Grid.Row="0"/>

因此,将2列网格从模板外部移动到那里,然后将scrollContentPresenter移动到左列,并将您的按钮移至右边。您还应该将按钮的列宽度设置为“自动”,以便获得所需的所有空间。最终的ControlTemplate应该看起来像这样:

<ControlTemplate x:Key="ScrollViewerTemplate1" TargetType="{x:Type ScrollViewer}">
    <Grid x:Name="Grid" Background="{TemplateBinding Background}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanHorizontallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" CanVerticallyScroll="False" Grid.Column="0" Content="{TemplateBinding Content}" CanContentScroll="{TemplateBinding CanContentScroll}" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
                <Button Grid.Column="1" MinWidth="20">te</Button>
            </Grid>
        </Grid>
        <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
        <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
    </Grid>
</ControlTemplate>

并且您的XAML应该看起来像这样:

<StackPanel>
    <ScrollViewer Template="{DynamicResource ScrollViewerTemplate1}" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
        <Grid Height="30" >
            <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
        </Grid>
    </ScrollViewer>
</StackPanel>

//i.sstatic.net/hsvva.png“ alt =”在此处输入图像描述”>

You'll need to re-template the ScrollViewer control. Start by extracting the template by moving the cursor over the ScrollViewer control and from the Properties pane select Miscellaneous -> Template -> Convert To New Resource (from the drop-down). The ScrollContentPresenter in the new template that appears is what draws everything inside the "client area":

<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanHorizontallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" CanVerticallyScroll="False" Grid.Column="0" Content="{TemplateBinding Content}" CanContentScroll="{TemplateBinding CanContentScroll}" Margin="{TemplateBinding Padding}" Grid.Row="0"/>

So move your 2-column grid from outside the template to that point there, and move the ScrollContentPresenter to it's left column and your button to it's right. You should also set the button's column width to "Auto" so that it gets all the space it needs. Final ControlTemplate should look like this:

<ControlTemplate x:Key="ScrollViewerTemplate1" TargetType="{x:Type ScrollViewer}">
    <Grid x:Name="Grid" Background="{TemplateBinding Background}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanHorizontallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" CanVerticallyScroll="False" Grid.Column="0" Content="{TemplateBinding Content}" CanContentScroll="{TemplateBinding CanContentScroll}" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
                <Button Grid.Column="1" MinWidth="20">te</Button>
            </Grid>
        </Grid>
        <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
        <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
    </Grid>
</ControlTemplate>

And your XAML should look like this:

<StackPanel>
    <ScrollViewer Template="{DynamicResource ScrollViewerTemplate1}" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
        <Grid Height="30" >
            <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf"  HorizontalAlignment="Left"></TextBlock>
        </Grid>
    </ScrollViewer>
</StackPanel>

Result:

enter image description here

狂之美人 2025-02-18 03:46:16

将完整的网格包装到scrollViewer中导致scrollviewer使其所有包含的元素可见IE可见。在您的情况下,它将使textblock按钮可滚动。

要允许按钮剪辑textblocktextblock.text.text几乎超过textblock的实际宽度,您可以将textblock单独包装到scrollviewer
这将导致textBlock能够隐藏或剪辑超过可用渲染宽度的文本,而用户仍然可以通过滚动完全查看它。

下面的示例将使滚动条出现,因为文本很快就对用户隐藏了,允许他仍然阅读所有文本:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled">
    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>
  <Button Grid.Column="1"
          HorizontalAlignment="Right"
          MinWidth="20">te</Button>
</Grid>

您的要求听起来像您想在用户中隐藏一定数量的文本,然后才能允许他滚动浏览。它使他能够阅读所有文本。
从用户体验的角度来看,我强烈建议您反对这种行为。
但是,为实现此目的,只需修改上面的示例即可向scrollViewer添加负面权利:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled"
                Padding="0,0,-150,0>
    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>
  <Button Grid.Column="1"
          HorizontalAlignment="Right"
          MinWidth="20">te</Button>
</Grid>

以上解决方案将剪辑超过文本,并将显示> scrollviewer在特定阈值之后(通过scrollviewer.padding),但不允许滚动整个隐藏的文本(仅在scrollviewer 变得可见)。

要启用整个隐藏文本的滚动,您可以定义一个简单的样式padding重置为 0 0 (实际上,它将切换填充),一旦可见滚动条:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition /n>
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>

  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled">
    <ScrollViewer.Style>

      <!-- Optionally, move this Style to a ResourceDictionary (e.g. App.xaml), 
           to make it apply to all ScrollViewer instance within the scope -->
      <Style TargetType="ScrollViewer">
        <Setter Property="Padding"
                Value="0,0,-150,0" />
        <Style.Triggers>
          <Trigger Property="ComputedHorizontalScrollBarVisibility"
                   Value="Visible">
            <Setter Property="Padding"
                    Value="0" />
          </Trigger>
        </Style.Triggers>
      </Style>
    </ScrollViewer.Style>

    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>

  <Button Grid.Column="1"
          MinWidth="20">te</Button>
</Grid>

Wrapping the complete Grid into a ScrollViewer results in the ScrollViewer to make all its contained elements visible i.e. scrollable. In your case, it will make the TextBlock and the Button scrollable.

To allow the Button to clip the TextBlock i.e. the TextBlock.Text to virtually exceed the actual width of the TextBlock, you can wrap the TextBlock alone into a ScrollViewer.
This will result in the TextBlock being able to hide or clip text that exceeds the available rendering width, while the user can still view it entirely by scrolling.

The following example will make the scroll bars appear as soon text has become hidden from the user, allowing him to still read all the text:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled">
    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>
  <Button Grid.Column="1"
          HorizontalAlignment="Right"
          MinWidth="20">te</Button>
</Grid>

Your requirement sounds like you want to hide certain amount of text from the user before he is allowed to scroll through it, enabling him to read all the text.
From a user experience point of view, I highly recommend against such a behavior.
However, to achieve this, simply modify the above example to add a negative right Padding to the ScrollViewer:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled"
                Padding="0,0,-150,0>
    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>
  <Button Grid.Column="1"
          HorizontalAlignment="Right"
          MinWidth="20">te</Button>
</Grid>

The above solution will clip the exceeding text and will show a ScrollViewer after a certain threshold (controlled via ScrollViewer.Padding), but will not allow to scroll the entire hidden text (only the portion from the moment on the ScrollViewer became visible).

To enable scrolling of the entire hidden text, you can define a simple Style that resets the Padding to 0 (in fact, it will toggle the Padding), once the scroll bars are visible:

<Grid Height="30">
  <Grid.ColumnDefinitions>
    <ColumnDefinition /n>
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>

  <ScrollViewer HorizontalScrollBarVisibility="Auto"
                VerticalScrollBarVisibility="Disabled">
    <ScrollViewer.Style>

      <!-- Optionally, move this Style to a ResourceDictionary (e.g. App.xaml), 
           to make it apply to all ScrollViewer instance within the scope -->
      <Style TargetType="ScrollViewer">
        <Setter Property="Padding"
                Value="0,0,-150,0" />
        <Style.Triggers>
          <Trigger Property="ComputedHorizontalScrollBarVisibility"
                   Value="Visible">
            <Setter Property="Padding"
                    Value="0" />
          </Trigger>
        </Style.Triggers>
      </Style>
    </ScrollViewer.Style>

    <TextBlock Text="testsdfqqsdfqsdqsdfqsdfqsdfqsdfqsdfsdqsdf" />
  </ScrollViewer>

  <Button Grid.Column="1"
          MinWidth="20">te</Button>
</Grid>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文