当滑块位于 StackPanel 内时如何展开滑块以填充可用空间

发布于 2024-08-16 11:01:57 字数 1049 浏览 7 评论 0原文

Grid 中插入 Slider 会扩展它以填充可用空间,但我不想使用网格,原因如下:

我有一个 TextBlockUserControl 中的 Slider,滑块是弹簧加载的,可以点动/往返;必须显示当前值,因为用户不能依赖中性光标的位置,因此文本块。实现此自定义滑块的 **Orientation** 属性需要旋转两个组件并调整它们的相对位置(左/右或上/下),这对于使用网格(除非我错过了一些明显的东西),而它是带有 StackPanel 的。

对 Aviad 评论的回应

Aviad,谢谢,我对造成的痛苦表示歉意;-) 问题在标题中:当滑块位于 StackPanel 内时,如何扩展滑块以填充可用空间?

此用户控件:

<UserControl x:Class="XXX.Preview.SelectionView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="auto" Width="auto">
    <GroupBox Header="Selected">
        <StackPanel Orientation="Horizontal">
            <TextBlock/>
            <Slider/>
        </StackPanel>
    </GroupBox>
</UserControl>

即使包含在具有“*”宽度的行中,也不会在包含在网格中时展开。滑块根本没有长度。

解决方案是在下面的代码中用网格替换堆栈面板,但我不想使用网格,因为当封闭用户控件时,我需要使用堆栈面板的 Orientation 属性来显示垂直堆叠的两个控件方向设置为“垂直”。

Inserting a Slider in a Grid would expand it to fill the available space, but I would prefer not use a grid for the following reason:

I've a TextBlock and a Slider in a UserControl, the slider is spring loaded and does jog / shuttle; the current value has to be displayed because the user can't rely on the neutral cursor's position, so the textblock. Implementing the **Orientation** property of this custom slider requires both components to be rotated and also their relative position to be adjusted (left/right or top/bottom), which wouldn't be easy with a grid (unless I miss something obvious) while it is with a StackPanel.

Response to Aviad's comment

Aviad, thanks, I apologize for the pain ;-) The question was in the title: How to expand a Slider to fill the available space when the slider is within a StackPanel ?

This user control:

<UserControl x:Class="XXX.Preview.SelectionView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="auto" Width="auto">
    <GroupBox Header="Selected">
        <StackPanel Orientation="Horizontal">
            <TextBlock/>
            <Slider/>
        </StackPanel>
    </GroupBox>
</UserControl>

won't expand when included in a grid even in a row with a "*" width. The slider will have no length at all.

A solution is to replace the stack panel by a grid in the code below, but I don't want to use a grid, because I need to use the Orientation property of the stack panel to show both controls stacked vertically when the enclosing user control is set in the Orientation "Vertical".

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

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

发布评论

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

评论(4

羅雙樹 2024-08-23 11:01:57

非常简单,只需绑定即可!
请注意,StackPanel 为 Horizo​​ntalAlignment="Stretch"
以及绑定积分引用的名称

            <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top" Orientation="Horizontal" Name="ParentPanel">
                <Slider Minimum="1" Maximum="999999" Interval="3" Width="{Binding Path=ActualWidth, ElementName=ParentPanel}"></Slider>
            </StackPanel>

@somedust

遵循此链接到类似的问题,并了解如何使用转换器更好地控制绑定。

Very simple with binding!
Note that the StackPanel as HorizontalAlignment="Stretch"
and a name referred to by the binding

            <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top" Orientation="Horizontal" Name="ParentPanel">
                <Slider Minimum="1" Maximum="999999" Interval="3" Width="{Binding Path=ActualWidth, ElementName=ParentPanel}"></Slider>
            </StackPanel>

Credits to @somedust

Follow this link to a similar question and learn how to have more control over the binding by using converters.

夏见 2024-08-23 11:01:57

您可以将滑块嵌入到具有像 Witdh="*" 这样的 ColumnDefinition 的网格列中(即,将分配可用空间)。例如,您可以在下面找到如何获取 TextBlock |滑块| TextBlock 布局,滑块拉伸以填充中间列的可用空间:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="CutOff Fraction:"/>
    <Slider  Grid.Column="1"  
             x:Name="SliderCutOffFraction"
             IsEnabled="{Binding ElementName=ChkLanczosFilter, Path=IsChecked}"
             HorizontalAlignment="Stretch"
             Margin="2" 
             Minimum="0.5"
             Maximum="5" 
             SmallChange="0.25"
             LargeChange="0.5" 
             TickPlacement="BottomRight" 
             TickFrequency="0.5"
             Value="1"            
             ValueChanged="SliderCutOffFraction_OnValueChanged"/>
    <TextBlock Grid.Column="2" Width="20"
               DockPanel.Dock="Right"
               Text="{Binding ElementName=SliderCutOffFraction, Path=Value}"
               TextAlignment="Center"/>
</Grid>

You can embed the Slider inside a Grid column that has a ColumnDefinition like Witdh="*" (i.e. will distribute available space). For example, below you can find how to get TextBlock | Slider | TextBlock layout with the slider stretched to fill the available space in the middle column:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="CutOff Fraction:"/>
    <Slider  Grid.Column="1"  
             x:Name="SliderCutOffFraction"
             IsEnabled="{Binding ElementName=ChkLanczosFilter, Path=IsChecked}"
             HorizontalAlignment="Stretch"
             Margin="2" 
             Minimum="0.5"
             Maximum="5" 
             SmallChange="0.25"
             LargeChange="0.5" 
             TickPlacement="BottomRight" 
             TickFrequency="0.5"
             Value="1"            
             ValueChanged="SliderCutOffFraction_OnValueChanged"/>
    <TextBlock Grid.Column="2" Width="20"
               DockPanel.Dock="Right"
               Text="{Binding ElementName=SliderCutOffFraction, Path=Value}"
               TextAlignment="Center"/>
</Grid>
捂风挽笑 2024-08-23 11:01:57

使用 DockPanel 而不是 StackPanel 可以更好地完成这件事。你可以尝试一下。

检查一下:
http://msdn.microsoft.com/en-us/library/bb628664。 aspx

http://www.wpftutorial.net/DockPanel.html

This thing can be better done by using DockPanel instead of StackPanel. You can try that.

Check this:
http://msdn.microsoft.com/en-us/library/bb628664.aspx

and http://www.wpftutorial.net/DockPanel.html

生活了然无味 2024-08-23 11:01:57

简短的回答是“你不能”。 StackPanel 受到其 ArrangeOverride 和 MeasureOverride 代码的限制。它根本不具备扩展以填充堆叠方向上的可用空间的能力。

当然,您可以子类化 StackPanel,并以不同的方式实现它,但 StackPanel 非常简单,如果您打算这样做,您也可以只子类化 Panel,或者您可以子类化 DockPanel(它具有扩展能力),然后设置DockPanel.Dock 基于其 StackPanel.Orientation 属性在其所有子级上:

public class StackPanelExpanding : DockPanel
{
  public Orientation Orientation
  {
    get { return (Orientation)GetValue(OrientationProperty); }
    set { SetValue(OrientationProperty, value); }
  }
  public static DependencyProperty OrientationProperty =
    StackPanel.OrientationProperty.AddOwner(typeof(StackPanelExpanding));

  protected override MeasureOverride(...)
  {
    var dock = Orientation==Orientation.Vertical ? Dock.Top : Dock.Left;
    foreach(var element in Children)
      SetDock(element, dock);
    base.MeasureOverride(...);
  }
}

您仍然没有弄清楚为什么不能仅使用 DockPanel 并在模板中使用触发器来同步 Orientation 和 DockPanel.Dock。坦率地说,在大多数情况下,我更倾向于采用这种方式,而不是创建自定义面板。

The short answer is "you can't." StackPanel is limited this way by its ArrangeOverride and MeasureOverride code. It simply does not have the ability to expand to fill available space in the stacking direction.

You could subclass StackPanel, of course, and implement it differently, but StackPanel is so simple that if you're going to do that you may as well just subclass Panel, or you could subclass DockPanel (which has the expansion ability), and set DockPanel.Dock on all its children based on its StackPanel.Orientation property:

public class StackPanelExpanding : DockPanel
{
  public Orientation Orientation
  {
    get { return (Orientation)GetValue(OrientationProperty); }
    set { SetValue(OrientationProperty, value); }
  }
  public static DependencyProperty OrientationProperty =
    StackPanel.OrientationProperty.AddOwner(typeof(StackPanelExpanding));

  protected override MeasureOverride(...)
  {
    var dock = Orientation==Orientation.Vertical ? Dock.Top : Dock.Left;
    foreach(var element in Children)
      SetDock(element, dock);
    base.MeasureOverride(...);
  }
}

You still didn't make it clear why you can't just use a DockPanel and use trigger in your template to synchronize the Orientation and DockPanel.Dock. Frankly in most cases I would be more inclined to go that way than to create a custom panel.

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