如何在 StackPanel 内扩展滑块以填充可用空间

6
在一个网格中插入滑块将使其扩展以填充可用空间,但出于以下原因,我更喜欢不使用网格:
我在一个UserControl中有一个TextBlock和一个Slider,该滑块具有弹簧加载功能并可进行抽动/接驳。必须显示当前值,因为用户无法依赖中性光标的位置。所以使用TextBlock。实现此自定义滑块的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 属性,在将封装用户控件设置为 "Vertical" 方向时显示两个控件垂直堆叠。

4个回答

6
非常简单的绑定!请注意,StackPanel 的 HorizontalAlignment="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的贡献。

点击链接查看类似问题,并学习如何使用转换器更好地控制绑定。


1
您可以将Slider嵌入到具有ColumnDefinition(如Witdh =“ *”)的网格列中(即将可用空间分配)。例如,下面是如何获取TextBlock | Slider | 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>

0

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

当然,您可以子类化StackPanel,并以不同的方式实现它,但StackPanel非常简单,如果您要这样做,您可能会直接子类化Panel,或者您可以子类化DockPanel(具有扩展功能),并根据其StackPanel.Orientation属性在所有子元素上设置DockPanel.Dock:

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并在模板中使用触发器来同步方向和DockPanel.Dock。坦白地说,在大多数情况下,我更倾向于这种方式,而不是创建自定义面板。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接