我如何在 Silverlight 中获得这种类型的布局?

发布于 2024-10-26 18:33:02 字数 414 浏览 1 评论 0 原文

我有一个列表框,它绑定到一个简单对象的列表。正如我们所知,默认情况下列表框将其项目托管为 Stackpanel,因此它以这种方式布置项目

item1
item2
item3
item4
item5
item6

但是我有一些条件,通过这些条件我检查项目是水平还是垂直显示,因此可以布置项目以这种方式

例如:-

item1
item2
item3 item4 item 5
item6

怎么可能做到这一点?

(如果你想知道为什么我需要这样的东西,一个示例场景是“facebook 风格更新”,其中如果用户连续上传 3-4 张照片,它们并不总是出现在下一行,但它可能会水平显示,而如果他发布一些事件,它会出现在下一行。)

提前致谢:)

I have a listbox and it's bound to a list of simple objects. As we know the listbox by default has it's items host as a Stackpanel and so it lays out items in this fashion

item1
item2
item3
item4
item5
item6

However i have some conditions through which i check whether the item is to be displayed horizontally or vertically and therefore the items could be laid out in this fashion

Eg :-

item1
item2
item3 item4 item 5
item6

How is it possible to do this?

(If you are wondering why would i ever need such a thing, an example scenario would be "facebook style updates" where if a user uploads 3-4 photos continously they don't always appear on the next line but it may appear horizontally whereas if he posts some event it appears in next line.)

Thanks in advance :)

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

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

发布评论

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

评论(2

一枫情书 2024-11-02 18:33:02

如果使用 MVVM 模式 我会做这样的事情:

  1. 为列表框所在的视图创建一个 ViewModel。此 VM 包含 ListItemViewModel 实例的集合(请参阅下一点)
  2. 创建一个名为 ListItemViewModel 的 ViewModel(给它一个更合适的名称,根据您的域)。该视图模型包含 ItemViewModel 实例的集合(请参阅下一点)。
  3. 创建一个名为 ItemViewModel 的 ViewModel。其中每一个都支持列表中的单个项目。根据您的域为其指定一个更合适的名称。
  4. 创建一个包含列表框的视图。将列表框绑定到 VM 中的 ListItemViewModel 集合。此列表框的项目模板将是 ListItemView(请参阅下一点)。项目面板模板将是默认的 StackPanel。
  5. 创建一个具有 ListItemViewModel 数据上下文的 ListItemView。该视图由 ItemViews 的水平 StackPanel 组成(请参见下一点)。
  6. 创建一个由 ItemViewModel 支持的 ItemView。

您的视图看起来像这样,每个视图都有一个相应的 ViewModel。

就像我上面说的,你肯定会想要更改视图/视图模型的名称,我的用于演示目的仅有的 :)

If using the MVVM pattern I would do something like this:

  1. Create a ViewModel for the view your list box is in. This VM contains a collection of ListItemViewModel instances (see next point)
  2. Create a ViewModel called ListItemViewModel (give it a more appropriate name, based on your domain). This view model contains a collection of ItemViewModel instances (see next point).
  3. Create a ViewModel called ItemViewModel. Each of these backs a single item in the list. Give this a more appropriate name based on your domain.
  4. Create a View that contains your listbox. Bind your listbox to the collection of ListItemViewModels in the VM. The item template for this list box will be a ListItemView (see next point). The items panel template will be the default StackPanel.
  5. Create a ListItemView which has a ListItemViewModel data context. This view consists of a horizontal StackPanel of ItemViews (see next point).
  6. Create an ItemView which is backed by the ItemViewModel.

Your view would look something like this, each with a correspoding ViewModel.

Like I said above, you'll definitely want to change the name of your views/view models, mine are for demonstration purposes only :)

最笨的告白 2024-11-02 18:33:02

该解决方案的基本原理是在 ListBoxItemTemplate 中使用另一个 ItemsControl。此 ItemsControl 应具有水平方向的 StackPanel 作为其 ItemsPanel

这是一个基本示例。让我们从一些非常简单的测试数据开始:-

public class TestStringList : List<string>
{
    public TestStringList()
    {
        AddRange(new[] {"Anthony", "Kar", "Martin", "Jon", "Erik", "Darin",
            "Balus", "Mike", "Hans", "Alex", "Anomie", "David" });

    }
}

现在我们想要在列表框中显示此列表,但将具有相同首字母缩写的所有名称保留在同一行。我将使用 IValueConverter 的实现来处理我们需要的分组。如果您使用 MVVM,那么您的 ViewModel 就会接受这一点。

public class Grouper : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((IEnumerable<string>)value).OrderBy(s => s).GroupBy(s => s[0]);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

该转换器的输出基本上是 IEnumerable> 这就是我们想要的。外部 ListBox 将枚举外部集合,内部 ItemsControl 将枚举内部字符串集,这些字符串将是一组具有相同首字母的名称。

这是 xaml:-

<UserControl x:Class="SilverlightApplication1.SimpleGrouping"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <local:TestStringList x:Key="TestData" />
        <local:Grouper x:Key="grouper" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox ItemsSource="{Binding Converter={StaticResource grouper}, Source={StaticResource TestData}}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal" />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" Margin="5" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

The fundementals of the solution is to use another ItemsControl in the ItemTemplate of the ListBox. This ItemsControl should have a horizontal oriented StackPanel as its ItemsPanel.

Here is a basic example. Lets start with some very simple testdata:-

public class TestStringList : List<string>
{
    public TestStringList()
    {
        AddRange(new[] {"Anthony", "Kar", "Martin", "Jon", "Erik", "Darin",
            "Balus", "Mike", "Hans", "Alex", "Anomie", "David" });

    }
}

Now we want to display this list in a ListBox but keep all the names that have the same first initial on the same line. I'm going to use an implementation of IValueConverter to deal with the grouping that we need. If you are using MVVM then you'd have your ViewModel take of this.

public class Grouper : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((IEnumerable<string>)value).OrderBy(s => s).GroupBy(s => s[0]);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The output of this converter is basically IEnumerable<IEnumerable<string>> which is what we want. The outer ListBox will enumerate the outer set and the inner ItemsControl will enumerate the inner set of strings which will be a set of names with the same initial.

Here is the xaml:-

<UserControl x:Class="SilverlightApplication1.SimpleGrouping"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <local:TestStringList x:Key="TestData" />
        <local:Grouper x:Key="grouper" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox ItemsSource="{Binding Converter={StaticResource grouper}, Source={StaticResource TestData}}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal" />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" Margin="5" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文