WPF 仅在可用空间中展开 RadPanelBarItem



我有一个RadPanelBar,每个RadPanelItem都有一个实体列表(每个项目中都有不同的列表)。列表中的每个项目都显示为分组框。对于大量项目,必须滚动RadPanelBar才能显示其他RadPanelBar项目。我希望滚动条出现在每个RadPanelBarItem中,以便所有RadPanelBarItems同时在屏幕上可见,如果项目的内容太长,用户只需要在每个RadPanelBarItem内滚动。

我正在使用每个 RadPanelBarItem 的 ItemsSource 属性,并设置其 ItemTemplate 以显示 GroupBoxes。

有没有一种好方法可以做到这一点,以便所有内容(高度等)都保持动态?

谢谢!

似乎没有简单的方法可以做到这一点。当我问一个类似的问题时,我从 Telerik 那里得到了以下回应:

如果我正确处理了您的情况,您有以下几种选择:

1) 设置面板栏项目的大小。这样,您将限制它们的大小。如果 您将项目的总和大小与应具有的面板栏大小相匹配 消除剪报。

2) 按顺序自定义面板栏和面板栏项控件模板 以支持自动按比例调整大小。在这种情况下,您应该 从面板栏控件模板中删除滚动查看器,并添加一个 顶级面板栏项控件模板中的滚动查看器(周围 项目演示者)。此外,您还应该将RadPanelBar ItemsPanel更改为 一个适当的面板。可能。它将是一个自定义面板 以垂直测量大小相等的物品。

我尝试做一个自定义面板并修改控件模板。我已经让它工作了,但它有很多代码,但这里是:

分布式高度面板.cs

这是自定义面板,用于执行布局并分配可用高度。

/// <summary>
/// Panel that distributes the available height amongst it's children (like a vertical StackPanel but the children are not allowed to be placed "outside" the parent's visual area).
/// </summary>
public class DistributedHeightPanel : Panel
{
    /// <summary>
    /// If set to a positive number, no child will get less height than specified.
    /// </summary>
    public double ItemsMinHeight
    {
        get { return (double)GetValue(ItemsMinHeightProperty); }
        set { SetValue(ItemsMinHeightProperty, value); }
    }
    public static readonly DependencyProperty ItemsMinHeightProperty =
        DependencyProperty.Register("ItemsMinHeight", typeof(double), typeof(DistributedHeightPanel), new UIPropertyMetadata(0.0));

    public DistributedHeightPanel()
        : base()
    {
    }
    protected override Size MeasureOverride(Size availableSize)
    {
        List<double> heights = new List<double>();
        //Find out how much height each child desire if it was the only child
        foreach (UIElement child in InternalChildren)
        {
            child.Measure(availableSize);
            heights.Add(child.DesiredSize.Height);
        }
        //Calculate ratio
        double ratio = GetRatio(availableSize.Height, heights);
        //Do the "real" Measure
        foreach (UIElement child in InternalChildren)
        {
            double actualHeight = child.DesiredSize.Height;
            if (ratio < 1)
            {
                //If ratio < 1 then the child can't have all the space it wants, calculate the new height
                actualHeight = child.DesiredSize.Height * ratio;
            }
            if (ItemsMinHeight > 0 && actualHeight < ItemsMinHeight)
            {
                //If ItemsMinHeight is set and the child is to small, then set the childs height to ItemsMinHeight
                actualHeight = ItemsMinHeight;
            }
            child.Measure(new Size(availableSize.Width, actualHeight));
        }
        return availableSize;
    }
    /// <summary>
    /// Calculates the ratio for fitting all heights in <paramref name="heightsToDistribute"/> in the total available height (as supplied in <paramref name="availableHeight"/>)
    /// </summary>
    private double GetRatio(double availableHeight, List<double> heightsToDistribute)
    {
        //Copy the heights list
        List<double> heights = new List<double>(heightsToDistribute);
        double desiredTotalHeight = heights.Sum();
        //If no height is desired then return 1
        if (desiredTotalHeight <= 0)
            return 1;
        //Calculate ratio
        double ratio = availableHeight / desiredTotalHeight;
        //We only want to compress so if ratio is higher than 1 return 1
        if (ratio > 1)
        {
            return 1;
        }
        //Check if heights become too small when the ratio is used
        int tooSmallCount = heights.Count(d => d * ratio < ItemsMinHeight);
        //If no or all all heights are too small: return the calculated ratio
        if (tooSmallCount == 0 || tooSmallCount == heights.Count)
        {
            return ratio;
        }
        else
        {
            //Remove the items which becomes too small and get a ratio without them (they will get ItemsMinHeight)
            heights.RemoveAll(d => d * ratio < ItemsMinHeight);
            return GetRatio(availableHeight - ItemsMinHeight * tooSmallCount, heights);
        }
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        //Arrange all children like a vertical StackPanel
        double y = 0;
        foreach (UIElement child in InternalChildren)
        {
            //child.DesiredSize.Height contains the correct value since it was calculated in MeasureOverride
            child.Arrange(new Rect(0, y, finalSize.Width, child.DesiredSize.Height));
            y += child.DesiredSize.Height;
        }
        return finalSize;
    }
}

MainWindow.xaml

包含名为 DistributedHeightRadPanelBarStyle 的样式和用于测试的 RadPanelBar 的控件模板。

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication9"
    Title="MainWindow" Height="350" Width="525" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<Window.Resources>
    <Style x:Key="DistributedHeightRadPanelBarStyle" TargetType="{x:Type telerik:RadPanelBar}">
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <local:DistributedHeightPanel ItemsMinHeight="22" /> <!-- 22 is fine for collapsed headers -->
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type telerik:RadPanelBar}">
                    <Grid>
                        <telerik:LayoutTransformControl x:Name="transformationRoot" IsTabStop="False">
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                <!-- <ScrollViewer x:Name="ScrollViewer" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalScrollBarVisibility="Auto" IsTabStop="False" Padding="{TemplateBinding Padding}" VerticalScrollBarVisibility="Auto" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">-->
                                <telerik:StyleManager.Theme>
                                    <telerik:Office_BlackTheme/>
                                </telerik:StyleManager.Theme>
                                <ItemsPresenter/>
                                <!--</ScrollViewer>-->
                            </Border>
                        </telerik:LayoutTransformControl>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Orientation" Value="Horizontal">
                            <Setter Property="LayoutTransform" TargetName="transformationRoot">
                                <Setter.Value>
                                    <RotateTransform Angle="-90"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Orientation" Value="Vertical"/>
    </Style>
</Window.Resources>
<Grid>
    <telerik:RadPanelBar Style="{StaticResource ResourceKey=DistributedHeightRadPanelBarStyle}" VerticalAlignment="Top" ExpandMode="Multiple" HorizontalAlignment="Stretch">
        <telerik:RadPanelBarItem DropPosition="Inside" Header="A - Colors" IsExpanded="True">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <StackPanel>
                    <TextBlock Height="100" Background="AliceBlue" Text="I'm AliceBlue" />
                    <TextBlock Height="100" Background="AntiqueWhite" Text="I'm AntiqueWhite" />
                </StackPanel>
            </ScrollViewer>
        </telerik:RadPanelBarItem>
        <telerik:RadPanelBarItem DropPosition="Inside" Header="B - Colors" IsExpanded="True">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <StackPanel>
                    <TextBlock Height="100" Background="Beige" Text="I'm Beige" />
                    <TextBlock Height="100" Background="Bisque" Text="I'm Bisque" />
                </StackPanel>
            </ScrollViewer>
        </telerik:RadPanelBarItem>
        <telerik:RadPanelBarItem DropPosition="Inside" Header="C - Colors">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <StackPanel>
                    <TextBlock Height="100" Background="CadetBlue" Text="I'm CadetBlue" />
                    <TextBlock Height="100" Background="Chartreuse" Text="I'm Chartreuse" />
                </StackPanel>
            </ScrollViewer>
        </telerik:RadPanelBarItem>
    </telerik:RadPanelBar>
</Grid>

也许这个解决方案对你来说太晚了,但希望有人会发现它很有用。

最新更新