Silverlight WrapPanel不能在手风琴内垂直拉伸

时间:2014-11-13 12:55:56

标签: c# .net silverlight accordion wrappanel

我的Silverlight应用程序中有一个带按钮的菜单屏幕。为此,我使用带有WrapPanel的ItemsControl作为ItemsPanel模板,因此按钮将换行到下一行(就像文本框中的文本一样)。

菜单是这样的:

enter image description here

现在我需要一个新功能:将按钮分组。所以我决定使用Accordion和ZeroOrMore项目。我使用ScrollViewer作为Accordion ContentTemplate, MaxHeight为150 将组高限制为150,然后使用垂直滚动条。在ScrollViewer中,有与WrapPanel和按钮相同的ItemsControl。

我希望WrapPanel有 3行项目而不滚动,所以我选择MaxHeight = 150是有原因的:因为每个按钮(带边距)的高度为50.这将允许3行没有滚动条。没有手风琴就行得很好,但是不能用它。

问题在于手风琴似乎并不理解WrapPanel高度,并假设它只有1行的高度,即带有边距的1个按钮的高度。因此,当我展开Accordion项目时,它的高度始终为50.如果我只有1行项目,那就没关系,但是如果我有2行或更多行,则高度不会增加到100或150,它就是'由于手风琴的高度不够,所以仍然显示50和滚动条。

以下是目前正在发生的事情: enter image description here

如果我手动设置ScrollViewer或WrapPanel的宽度或高度,则问题不会发生。但它是一个可调整大小的窗口,我不知道它的大小或每个组中的数量。用户自定义,因此我无法设置高度或宽度。我需要Accordion来正确计算高度。

在这里,出于测试目的,我设置了ScrollViewer Width = 350 (比Accordion / UserControl宽度略小,所以我们可以很容易地看到它),以及MaxHeight = 100 (因此对第二组来说还不够)。 enter image description here

上图显示了我想要的内容,但没有宽度,因此用户可以调整窗口大小并在屏幕上显示更多按钮。

当我展开手风琴时,我注意到WrapPanel动态调整按钮,因为我可以看到它发生,我可以看到从第一行末尾到下一行的物品。所以我假设,在扩展手风琴之前,WrapPanel没有宽度(可能是它的无穷大),这就是它还没有包裹按钮的原因。它"认为"第一行中的所有项目都有空间。

以下是我写的用于显示问题的Silverlight应用程序。 MainPage.xaml

    <ScrollViewer Padding="0" BorderThickness="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="5">
    <Grid>
        <toolkit:Accordion HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10"
                           HorizontalContentAlignment="Left" VerticalContentAlignment="Stretch" 
                           ItemsSource="{Binding Groups}" SelectionMode="ZeroOrMore">

            <toolkit:Accordion.ItemContainerStyle>
                <Style TargetType="toolkit:AccordionItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </toolkit:Accordion.ItemContainerStyle>

            <toolkit:Accordion.AccordionButtonStyle>
                <Style TargetType="toolkit:AccordionButton">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="toolkit:AccordionButton">
                                <Border Background="LightCyan" BorderBrush="Black" BorderThickness="1">
                                    <TextBlock Text="{Binding Description}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </toolkit:Accordion.AccordionButtonStyle>

            <toolkit:Accordion.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <ScrollViewer MaxHeight="150" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" >
                            <ItemsControl ItemsSource="{Binding Items}" >
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <toolkit:WrapPanel HorizontalAlignment="Left" Margin="10"/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>

                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Button HorizontalContentAlignment="Left" Margin="3" Width="195" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{Binding Description}"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Grid>
                </DataTemplate>
            </toolkit:Accordion.ContentTemplate>
        </toolkit:Accordion>
    </Grid>
</ScrollViewer>

C#中的代码: MainPage.xaml.cs ,其属性为&#39;用于添加样本组/项目的绑定和代码:

public partial class MainPage : UserControl, INotifyPropertyChanged
{
    public class ItemViewModel
    {
        public string Description { get; set; }
    }

    public class GroupViewModel
    {
        public List<ItemViewModel> Items { get; set; }
        public string Description { get; set; }
    }

    public List<ItemViewModel> Items { get; set; }
    public List<GroupViewModel> Groups { get; set; }

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;

        this.Groups = new List<GroupViewModel>();
        GroupViewModel g1, g2, g3;

        this.Groups.Add(g1 = new GroupViewModel() { Description = "Group with 4 itens", Items = new List<ItemViewModel>() });
        g1.Items.Add(new ItemViewModel() { Description = "item1" } );
        g1.Items.Add(new ItemViewModel() { Description = "item2" } );
        g1.Items.Add(new ItemViewModel() { Description = "item3" } );
        g1.Items.Add(new ItemViewModel() { Description = "item4" } );

        this.Groups.Add(g2 = new GroupViewModel() { Description = "Group with 10 itens", Items = new List<ItemViewModel>() });
        g2.Items.Add(new ItemViewModel() { Description = "item1" } );
        g2.Items.Add(new ItemViewModel() { Description = "item2" } );
        g2.Items.Add(new ItemViewModel() { Description = "item3" } );
        g2.Items.Add(new ItemViewModel() { Description = "item4" } );
        g2.Items.Add(new ItemViewModel() { Description = "item5" } );
        g2.Items.Add(new ItemViewModel() { Description = "item6" } );
        g2.Items.Add(new ItemViewModel() { Description = "item7" } );
        g2.Items.Add(new ItemViewModel() { Description = "item8" } );
        g2.Items.Add(new ItemViewModel() { Description = "item9" } );
        g2.Items.Add(new ItemViewModel() { Description = "item10" } );

        this.Groups.Add(g3 = new GroupViewModel() { Description = "Group with 3 itens", Items = new List<ItemViewModel>() });
        g3.Items.Add(new ItemViewModel() { Description = "item1" } );
        g3.Items.Add(new ItemViewModel() { Description = "item2" });
        g3.Items.Add(new ItemViewModel() { Description = "item3" });

        NotifyPropertyChanged("Groups");

    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

2 个答案:

答案 0 :(得分:1)

我找到了一个解决方案,但我不得不删除手风琴,对我来说不是什么问题。 我使用了ItemsControl作为&#34; Accordions&#39;列表&#34;使用Button作为AccordionButton。其余的保持不变,一个带有ItemsControl和WrapPanel的ScrollViewer。

ScrollViewer具有绑定到其高度。 Button有一个Command,它将ScrollViewer的高度更改为0以折叠项目,并将NaN更改为扩展。工作完美无瑕。

这是XAML:

<ItemsControl HorizontalAlignment="Stretch" VerticalAlignment="Top" ItemsSource="{Binding Groups}" 
            HorizontalContentAlignment="Left" VerticalContentAlignment="Stretch"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Margin="0">

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <Grid.RowDefinitions>
                    <RowDefinition Height="24"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <Button Grid.Row="0" Command="{Binding ExpandCommand}" Content="{Binding Description}"/>

                <ScrollViewer Grid.Row="1" Padding="0" VerticalScrollBarVisibility="Auto" MaxHeight="100" BorderThickness="0"
                                HorizontalScrollBarVisibility="Disabled" Height="{Binding ContentHeight}" HorizontalAlignment="Stretch">
                    <ItemsControl ItemsSource="{Binding Items}" >
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <toolkit:WrapPanel HorizontalAlignment="Left" Margin="10"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>

                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Button HorizontalContentAlignment="Left" Margin="3" Width="80" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{Binding Description}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ScrollViewer>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

和xaml.cs:

public partial class MainPage : UserControl, INotifyPropertyChanged
{
    public class ItemViewModel
    {
        public string Description { get; set; }
    }

    public class GroupViewModel : INotifyPropertyChanged
    {
        public GroupViewModel()
        {
            ContentHeight = double.NaN;
            NotifyPropertyChanged("ContentHeight");
            ExpandCommand = new DelegateCommand<object>(Expand);
        }
        public List<ItemViewModel> Items { get; set; }
        public string Description { get; set; }
        public double ContentHeight { get; set; }

        public DelegateCommand<object> ExpandCommand { get; set; }
        public void Expand(object obj)
        {
            if (double.IsNaN(this.ContentHeight)) this.ContentHeight = 0;
            else this.ContentHeight = double.NaN;
            NotifyPropertyChanged("ContentHeight");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
    }

    public List<ItemViewModel> Items { get; set; }
    public List<GroupViewModel> Groups { get; set; }

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;

        this.Groups = new List<GroupViewModel>();
        GroupViewModel g1, g2, g3;

        this.Groups.Add(g1 = new GroupViewModel() { Description = "Group with 4 itens", Items = new List<ItemViewModel>() });
        g1.Items.Add(new ItemViewModel() { Description = "item1" } );
        g1.Items.Add(new ItemViewModel() { Description = "item2" } );
        g1.Items.Add(new ItemViewModel() { Description = "item3" } );
        g1.Items.Add(new ItemViewModel() { Description = "item4" } );

        this.Groups.Add(g2 = new GroupViewModel() { Description = "Group with 10 itens", Items = new List<ItemViewModel>() });
        g2.Items.Add(new ItemViewModel() { Description = "item1" } );
        g2.Items.Add(new ItemViewModel() { Description = "item2" } );
        g2.Items.Add(new ItemViewModel() { Description = "item3" } );
        g2.Items.Add(new ItemViewModel() { Description = "item4" } );
        g2.Items.Add(new ItemViewModel() { Description = "item5" } );
        g2.Items.Add(new ItemViewModel() { Description = "item6" } );
        g2.Items.Add(new ItemViewModel() { Description = "item7" } );
        g2.Items.Add(new ItemViewModel() { Description = "item8" } );
        g2.Items.Add(new ItemViewModel() { Description = "item9" } );
        g2.Items.Add(new ItemViewModel() { Description = "item10" } );

        this.Groups.Add(g3 = new GroupViewModel() { Description = "Group with 3 itens", Items = new List<ItemViewModel>() });
        g3.Items.Add(new ItemViewModel() { Description = "item1" } );
        g3.Items.Add(new ItemViewModel() { Description = "item2" });
        g3.Items.Add(new ItemViewModel() { Description = "item3" });

        NotifyPropertyChanged("Groups");

    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


}

答案 1 :(得分:0)

我觉得这并没有完全回答这个问题,但如果我删除ScrollViewers MaxHeight属性并相反指定Wrappanel的MaxWidth为620,则可以获得垂直视图最少有3个按钮,手风琴相应地增长/缩小没有滚动条。

权衡是当用户增加屏幕尺寸宽度时,按钮始终保持3行而忽略额外的水平空间。

<toolkit:Accordion.ContentTemplate>
    <DataTemplate>
        <Grid>
            <ScrollViewer VerticalScrollBarVisibility="Auto"
                            HorizontalScrollBarVisibility="Disabled">
                <ItemsControl ItemsSource="{Binding Items}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <toolkit:WrapPanel HorizontalAlignment="Left"
                                                MaxWidth="620"
                                                Margin="10" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>

enter image description here