簡體   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