Home > front end >  Create new stackpanel from an existing one
Create new stackpanel from an existing one

Time:06-21

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:

        <StackPanel Orientation="Horizontal">
        <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="FileName" />
            </StackPanel>
            
        </Border>
    </StackPanel>

The existing logic:

        public void UploadFileToLibrary(object sender, RoutedEventArgs e)
    {
        bool fileHasBeenAdded = false;

        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);
            FileNameHolder.Text = filename;
            globalFilepath = filepath;
        }

        fileHasBeenAdded = true;

        if (fileHasBeenAdded)
        {
            // Save the added file locally
            // System.Diagnostics.Debug.WriteLine("File has been added locally");
            
        }
    }

CodePudding user response:

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

CodePudding user response:

You could clone the StackPanel using the System.Windows.Markup.XamlWriter class:

string xaml = XamlWriter.Save(FileContentHolder);
StackPanel newStackPanel = (StackPanel)XamlReader.Parse(xaml);
Button openPdf = newStackPanel.FindName("OpenPDF") as Button;
if (openPdf != null)
{
    openPdf.Click  = OpenFile;
}
root.Children.Add(newStackPanel);

Note that you'll have to programmatically re-attach any event handlers:

Serialization Limitations of XamlWriter.Save

  • Related