微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何以编程方式在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.jb51.cc/csharp/99335.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐