【问题标题】:How to make WPF listview display Images and Labels dynamically如何使 WPF listview 动态显示图像和标签
【发布时间】:2016-03-04 00:46:10
【问题描述】:

我很难为 WPF 窗口创建 UI。我正在尝试(动态)显示一堆带有电影名称的电影海报,直接在图像下方。 ItemsSource 通过foreach 迭代分配给图像列表。图像文件本身可能有不同的大小,但如下所示,我将设置一个统一的大小。

基本上,我的目标是让它看起来像这样:

到目前为止,我的代码只显示一个带有一个大水平行(?)的窗口,图像在中心,没有标签。这是我的 XAML 代码:

<Window x:Name="TVWindow" x:Class="PACS_Pre_Alpha.TV"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="TV" Height="746" Width="1000" ResizeMode="NoResize">
<Grid x:Name="TVGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
    </Grid.RowDefinitions>
    <ListView x:Name="TvBox" HorizontalAlignment="Left" Height="648" VerticalAlignment="Top" Width="994" Grid.Row="5" Grid.Column="5">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="5" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
                    <Image Source="{Binding ImageData}" HorizontalAlignment="Center" VerticalAlignment="Top" />
                    <TextBlock Text="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

我的电影是用这个 C# 代码添加的:

foreach (string tvf in ContentFiles)
{
            string ContentTitle = System.IO.Path.GetFileNameWithoutExtension(tvf);
            MovieData cnt = new MovieData();
            cnt.ImageData = LoadImage(ActualImage);
            cnt.Title = ContentTitle;
            ContentDataList.Add(cnt);

}
        TvBox.ItemsSource = ContentDataList;

编辑:我已经按照@MarkFeldman 的建议更改了我的 XAML 标记,但现在什么也没有出现。 编辑:它目前看起来像这样:

【问题讨论】:

  • 你能发布你的完整源代码吗?我想做类似的事情,这对我来说是一个很好的基石!

标签: wpf xaml listview


【解决方案1】:

您将提供有关数据本身的更多信息,即它的格式是什么,如何将其分配给 ItemsSource 等。一方面,您没有设置 ItemTemplate,因此您可能想先看一下.例如,如果您有一个包含您的电影数据的类,如下所示:

public class MovieData
{
    private string _Title;
    public string Title
    {
        get { return this._Title; }
        set { this._Title = value; }
    }

    private BitmapImage _ImageData;
    public BitmapImage ImageData
    {
        get { return this._ImageData; }
        set { this._ImageData = value; }
    }

}

然后你会用这样的方式显示它:

<ListView.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
            <Image Source="{Binding ImageData}" HorizontalAlignment="Center" VerticalAlignment="Top"/>
            <TextBlock Text="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </StackPanel>
    </DataTemplate>
</ListView.ItemTemplate>

更新:

抱歉,我认为您显然仍需要使用 UniformGrid。以下是您的完整 XAML 的外观:

<ListView x:Name="TvBox" HorizontalAlignment="Stretch" VerticalAlignment="Top">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="5" HorizontalAlignment="Stretch"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                <Image Source="{Binding ImageData}" HorizontalAlignment="Stretch" VerticalAlignment="Top" Stretch="UniformToFill" />
                <TextBlock Text="{Binding Title}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

我已经为您提供了 MovieData 类,因此您的 Window 代码应如下所示:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        this.TvBox.ItemsSource = new MovieData[]
        {
            new MovieData{Title="Movie 1", ImageData=LoadImage("image.jpg")},
            new MovieData{Title="Movie 2", ImageData=LoadImage("image.jpg")},
            new MovieData{Title="Movie 3", ImageData=LoadImage("image.jpg")},
            new MovieData{Title="Movie 4", ImageData=LoadImage("image.jpg")},
            new MovieData{Title="Movie 5", ImageData=LoadImage("image.jpg")},
            new MovieData{Title="Movie 6", ImageData=LoadImage("image.jpg")}
        };
    }

    // for this code image needs to be a project resource
    private BitmapImage LoadImage(string filename)
    {
        return new BitmapImage(new Uri("pack://application:,,,/" + filename));
    }
}

在此示例中,我假设您的项目中有一个名为“image.jpg”的图像,该图像已设置为构建操作“资源”,如果您的图像来自其他地方,那么您需要修改 LoadImage 代码相应地。

【讨论】:

  • 这看起来不错,但是如何通过 MovieData 类从 c# 代码设置单个电影?
  • 我使用foreach 迭代为我添加的每部电影(分配类变量)创建了一个MovieData 对象,但没有任何反应。
  • 我没有看到你的代码,所以没有。它可以是任何东西。如果您将代码添加到问题中,我很乐意再次查看。
  • 您可以在 XAML 中声明它们,您不需要在代码隐藏中专门设置所有内容。事实上,使用 WPF,您应该尽可能地依赖数据绑定,即使您没有使用成熟的 MVVM。只需将 MouseDown="Image_MouseDown" 添加到 XAML 中的图像,然后在主窗口中添加 Image_MouseDown 处理程序。处理程序的 sender 参数将指向 Image 控件,其 DataContext 将设置为关联的 MovieData 对象。
  • 没问题....这是因为您使用了ListView,它最终继承了ItemsControl,但添加了滚动和项目选择等附加功能。如果您不想要这些功能然后将ListView 更改为ItemsControl。如果您仍然想要滚动,那么您还必须将其包装在 &lt;ScrollViewer&gt; 中。
【解决方案2】:

我用 UniformGrid 做了一些非常相似的事情我看到你没有设置你的 UniformGrid 的行。我在我的游戏应用程序中做到了这一点。很好的方法,但很难做到正确。设置一个 ItemTemplate。并尝试使用 ItemsControl 外部对象而不是列表视图

<ItemsControl  IsEnabled="{Binding GameBoardEnabled}" 
                x:Name="_board" 
                ItemsSource ="{Binding Board}" 
                ItemTemplate= "{DynamicResource GamePieceTemplate}"  >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <!--<StackPanel/>-->
                        <UniformGrid                          
                            Columns="{Binding Columns}" 
                            Rows   ="{Binding Rows}"  />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

【讨论】:

  • 除非 SO 想要项目选择和键盘导航等,在这种情况下 ListView 可能是正确的。
  • UniformGrids 总是必须有行+列我很确定。所以这可能是大部分答案。
  • 如果您的意思是项目必须指定行号和列号,那么不,那只是网格。 UniformGrids 只是采用常规集合并自动进行行/列布局。如果它在 ListView 中,那么键盘箭头按钮也将被解释为更正以更改当前选定的项目。
  • 你是对的马克。不需要行/列。但是网格上有行/列 - 但这是一个附带问题。
  • @Luke 是的! Rows 是一个 ViewModel 变量,用于描述 UniformGrid 中的行数。同样,Columns 对 Columns 执行相同的任务。我在回答您的问题和 fm Mark Feldman 的意见时了解到,您只需要设置一个或另一个。在你的情况下,我说你需要在你的虚拟机中决定你想要多少列。 GamePiece 模板还绘制了一个矩形并用图像填充它:有关使用此技术的完整示例:codeproject.com/Articles/991634/…
猜你喜欢
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2011-09-26
  • 2020-06-29
相关资源
最近更新 更多