Search code examples
c#wpfxamlmvvm

Create new stackpanel from an existing one


I have this fileholder marked as 2. on the image. When I click on Upload PDF I want to create a new exactly the same looking fileholder from it's existing xaml after I have added a new file.

What im trying to ask is how can I access the xaml so that this would be possible?

enter image description here

The XAML:

<UserControl
x:Class="ModernDesign.MVVM.View.LibraryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ModernDesign.MVVM.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="460"
d:DesignWidth="800"
mc:Ignorable="d">
<StackPanel>
    <TextBlock
        Margin="0,20,0,0"
        HorizontalAlignment="Center"
        FontFamily="/Fonts/#TiroGurmukhi"
        FontSize="28"
        Foreground="White"
        Text="Your PDF Library" />

    <StackPanel
        Margin="0,10,0,0"
        HorizontalAlignment="Center"
        Orientation="Horizontal">

        <Button
            x:Name="UploadButton"
            Width="70"
            Background="White"
            Click="UploadFileToLibrary"
            Content="Upload PDF"
            Cursor="Hand">
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="5" />
                </Style>
            </Button.Resources>
        </Button>
    </StackPanel>

    <StackPanel Orientation="Horizontal">
        <Border Width="192">
            <StackPanel x:Name="FileContentHolder">
                <Border
                    Width="110"
                    Height="105"
                    HorizontalAlignment="Center"
                    Background="#844eff"
                    CornerRadius="10">

                    <Button
                        x:Name="OpenPDF"
                        Width="45"
                        Margin="0,75,0,15"
                        HorizontalAlignment="Center"
                        Background="White"
                        Click="OpenFile">
                        <Button.Resources>
                            <Style TargetType="Border">
                                <Setter Property="CornerRadius" Value="5" />
                            </Style>
                        </Button.Resources>
                        <TextBlock
                            HorizontalAlignment="Center"
                            FontSize="9"
                            Foreground="#3b3939"
                            Text="Open" />
                    </Button>

                </Border>
                <TextBlock
                    x:Name="FileNameHolder"
                    Margin="0,5,0,0"
                    HorizontalAlignment="Center"
                    FontFamily="/Fonts/#TiroGurmukhi"
                    FontSize="12"
                    Foreground="White"
                    Text="FileName" />
            </StackPanel>
        </Border>
    </StackPanel>

</StackPanel>

The existing logic:

    public partial class LibraryView : UserControl
{
    string globalFilepath;

    public LibraryView()
    {
        InitializeComponent();
    }


    public void UploadFileToLibrary(object sender, RoutedEventArgs e)
    {
        Microsoft.Win32.OpenFileDialog openFileDialog = new OpenFileDialog();
        openFileDialog.Filter = "pdf files (*.pdf)|*.pdf|All files (*.*)|*.*";

        bool? response = openFileDialog.ShowDialog();

        if (response == true)
        {
            string filepath = openFileDialog.FileName;
            string filename = Path.GetFileNameWithoutExtension(filepath);
            //string fullpath = Path.GetFullPath(filepath);
            FileNameHolder.Text = filename;
            globalFilepath = filepath;
        }
    }


    public void OpenFile(object sender, RoutedEventArgs e)
    {
        var openSelectedFile = new Process();
        openSelectedFile.StartInfo = new ProcessStartInfo(globalFilepath)
        { UseShellExecute = true };

        openSelectedFile.Start();
    }
}

Solution

  • You should define the repeating layout elements as DataTemplate and then show it using a ListBox. The items of the ListBox are the filenames.
    You can redefine the ListBox.ItemsPanel to configure it to display the items horizontally.

    MainWindow.xaml

    <Window>
      <ListBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=UploadedFiles}">
        <ListBox.ItemsPanel>
          <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Horizontal" />
          </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    
        <ListBox.ItemTemplate>
          <DataTemplate>
            <Border Width="192"
                    x:Name="Stack">
              <StackPanel x:Name="FileContentHolder">
                <Border Width="110"
                        Height="105"
                        HorizontalAlignment="Center"
                        Background="#844eff"
                        CornerRadius="10">
    
                  <Button x:Name="OpenPDF"
                          Width="45"
                          Margin="0,75,0,15"
                          HorizontalAlignment="Center"
                          Background="White"
                          Click="OpenFile">
                    <Button.Resources>
                      <Style TargetType="Border">
                        <Setter Property="CornerRadius"
                                Value="5" />
                      </Style>
                    </Button.Resources>
                    <TextBlock HorizontalAlignment="Center"
                               FontSize="9"
                               Foreground="#3b3939"
                               Text="Open" />
                  </Button>
                </Border>
                <TextBlock x:Name="FileNameHolder"
                           Margin="0,5,0,0"
                           HorizontalAlignment="Center"
                           FontFamily="/Fonts/#TiroGurmukhi"
                           FontSize="12"
                           Foreground="White"
                           Text="{Binding}" />
              </StackPanel>
            </Border>
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>
    </Window>
    

    MainWindow.xaml.cs

    // The binding source for the ListView
    public ObservableCollection<string> UploadedFiles
    {
      get => (ObservableCollection<string>)GetValue(UploadedFilesProperty);
      set => SetValue(UploadedFilesProperty, value);
    }
    
    public static readonly DependencyProperty UploadedFilesProperty = DependencyProperty.Register(
      "UploadedFiles",
      typeof(ObservableCollection<string>),
      typeof(MainWindow),
      new PropertyMetadata(default));
    
    public MainWindow()
    {
      InitializeComponent();
    
      this.UploadedFiles = new ObservableCollection<string>();
    
      // TODO::If necessary initialize UploadedFiles collection with filenames
    }
    
    public void UploadFileToLibrary(object sender, RoutedEventArgs e)
    {
      Microsoft.Win32.OpenFileDialog openFileDialog = new OpenFileDialog();
      openFileDialog.Filter = "pdf files (*.pdf)|*.pdf|All files (*.*)|*.*";
    
      bool? response = openFileDialog.ShowDialog();
      if (response == true)
      {
        string filepath = openFileDialog.FileName;
        string filename = Path.GetFileNameWithoutExtension(filepath);
    
        // Display a new "fileholder" box in the view
        this.UploadedFiles.Add(filename);
    
        ...
      }
    
      ...
    }
    

    See