繁体   English   中英

如何以编程方式在C#中创建WPF可滚动StackPanel列表

[英]How to programmatically create WPF scrollable StackPanel list in C#

我的情况:

我正在开发一个C#WPF应用程序(在Windows上),我需要在运行时动态创建很多控件。 由于应用程序的性质,我无法在WPF窗口的许多方面使用标准XAML(带有模板)。 这是一个非常独特的案例,不,我不会重新考虑我的申请格式。

我想要完成的事情:

我想以编程方式创建一个控件,显示StackPanel (或任何其他有效的控件组)的可滚动列表,对于一个用例,每个控件都将包含一个TextBlock控件顶部的Image控件(图片)(title /字幕):

  • 我更愿意在没有任何数据绑定的情况下完成所有这些(参见下面的推理)。 因为项目是在运行时定义的,所以我应该能够通过迭代在没有它们的情况下完成这项工作。
  • 控件/查看器应该能够有多个列/行,因此它不是一维的(就像典型的ListBox控件一样)。
  • 它也应该可以互换,以便您可以修改 (添加,删除等)控件中的项目。

我已经包含了一张图片(下图),为您提供了一个可能的用例示例。

过去 ,我已经能够通过使用带有ItemTemplate (包装在ScrollViewer )的ListView使用XAML来完成所有这些。 但是,完全使用C#代码执行此操作会使其更加困难。 我最近使用简单的c#代码创建了ControlTemplate (使用FrameworkElementFactory s。它可能会有点复杂,我不确定它是否是最佳实践。我应该尝试使用相同的路径(使用ListView和模板) )?如果是这样,怎么样?或者使用C#代码实现更简单,更优雅的选项?

在此输入图像描述

编辑:我真的不想使用任何数据绑定。 我只想创建一个StackPanels的(可滚动的)列表,我可以轻松地修改/调整它。 使用数据绑定感觉就像是向后实现,并且违背了运行时动态特性的目的。

编辑2(1/25/2018):回复不多。 我只需要一个统一的,可滚动的stackpanel列表 我可以调整它以满足我的需求,但它需要全部用C#(代码隐藏)。 如果有人需要更多信息/澄清,请告诉我。 谢谢。

链接到XAML POST

这里有一个办法做到这一点在代码中使用ListBoxUniformGridItemsPanelTemplate 或者,您只能使用UniformGrid并将其放在ScrollViewer ,但由于ListBox已经处理了选择和所有这些内容,您可能最好坚持使用它。 此代码将根据可用宽度自动调整一行中的项目数。

MoviePresenter.cs:

public class MoviePresenter : ListBox
{
    public MoviePresenter()
    {
        FrameworkElementFactory factory = new FrameworkElementFactory(typeof(UniformGrid));
        factory.SetBinding(
            UniformGrid.ColumnsProperty,
            new Binding(nameof(ActualWidth))
            {
                Source = this,
                Mode = BindingMode.OneWay,
                Converter = new WidthToColumnsConverter()
                {
                    ItemMinWidth = 100
                }
            });

        ItemsPanel = new ItemsPanelTemplate()
        {
            VisualTree = factory
        };
    }
}

internal class WidthToColumnsConverter : IValueConverter
{
    public double ItemMinWidth { get; set; } = 1;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double? actualWidth = value as double?;
        if (!actualWidth.HasValue)
            return Binding.DoNothing;

        return Math.Max(1, Math.Floor(actualWidth.Value / ItemMinWidth));
    }

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

MovieItem.cs:

public class MovieItem : Grid
{
    public MovieItem()
    {
        RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
        RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
        RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
        RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });

        Image image = new Image();
        image.Stretch = Stretch.UniformToFill;
        image.SetBinding(Image.SourceProperty, new Binding(nameof(ImageSource)) { Source = this });
        Children.Add(image);

        TextBlock title = new TextBlock();
        title.FontSize += 1;
        title.FontWeight = FontWeights.Bold;
        title.Foreground = Brushes.Beige;
        title.TextTrimming = TextTrimming.CharacterEllipsis;
        title.SetBinding(TextBlock.TextProperty, new Binding(nameof(Title)) { Source = this });
        Grid.SetRow(title, 1);
        Children.Add(title);

        TextBlock year = new TextBlock();
        year.Foreground = Brushes.LightGray;
        year.TextTrimming = TextTrimming.CharacterEllipsis;
        year.SetBinding(TextBlock.TextProperty, new Binding(nameof(Year)) { Source = this });
        Grid.SetRow(year, 2);
        Children.Add(year);

        TextBlock releaseDate = new TextBlock();
        releaseDate.Foreground = Brushes.LightGray;
        releaseDate.TextTrimming = TextTrimming.CharacterEllipsis;
        releaseDate.SetBinding(TextBlock.TextProperty, new Binding(nameof(ReleaseDate)) { Source = this });
        Grid.SetRow(releaseDate, 3);
        Children.Add(releaseDate);
    }

    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.Register("ImageSource", typeof(string), typeof(MovieItem), new PropertyMetadata(null));

    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(MovieItem), new PropertyMetadata(null));

    public static readonly DependencyProperty YearProperty =
        DependencyProperty.Register("Year", typeof(string), typeof(MovieItem), new PropertyMetadata(null));

    public static readonly DependencyProperty ReleaseDateProperty =
        DependencyProperty.Register("ReleaseDate", typeof(string), typeof(MovieItem), new PropertyMetadata(null));

    public string ImageSource
    {
        get { return (string)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }

    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    public string Year
    {
        get { return (string)GetValue(YearProperty); }
        set { SetValue(YearProperty, value); }
    }

    public string ReleaseDate
    {
        get { return (string)GetValue(ReleaseDateProperty); }
        set { SetValue(ReleaseDateProperty, value); }
    }
}

MainWindow.xaml:

<Grid>
    <local:MoviePresenter x:Name="moviePresenter" 
                          ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</Grid>

MainWindow.xaml.cs

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

        for (int i = 0; i < 20; i++)
        {
            DateTime dummyDate = DateTime.Now.AddMonths(-i).AddDays(-(i * i));

            MovieItem item = new MovieItem()
            {
                ImageSource = $"http://fakeimg.pl/100x200/?text=Image_{i}",
                Title = $"Dummy movie {i}",
                Year = $"{dummyDate.Year}",
                ReleaseDate = $"{dummyDate.ToLongDateString()}"
            };

            moviePresenter.Items.Add(item);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM