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

前端之家收集整理的这篇文章主要介绍了如何以编程方式在C#中创建WPF可滚动StackPanel列表前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的情况:

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

我想要完成的事情:

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

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

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

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

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

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

LINK TO XAML POST

解决方法

这是使用带有UniformGrid作为ItemsPanelTemplate的ListBox代码中执行此操作的方法.或者,您只能使用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,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",new PropertyMetadata(null));

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

    public static readonly DependencyProperty ReleaseDateProperty =
        DependencyProperty.Register("ReleaseDate",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);
        }
    }
}
原文链接:https://www.f2er.com/csharp/99335.html

猜你在找的C#相关文章