sapbucket
sapbucket

Reputation: 7195

how to copy paste a WPF Window (clone) and not have errors

I am using .Net 4.5.2 with WPF and C# 5.0. I created a Window in a WPF project. I would like to copy paste this window in the solution explorer, making a second window, and rename it to a new name.

When I do this, the new (copied) window's InitializeComponent() method always gives me an error. How does one cleanly copy a window (and it's code, etc.) in the solution explorer?

This question was answered partially here: Copy pasting WPF window gives error however the answer did not solve my issue.

My approach (that does not work):

  1. Create a window and title it WindowTest
  2. In the solution explorer, select WindowTest and copy, then paste it into the same project
  3. Rename the new copied Window to WindowTestCopy
  4. In WindowTestCopy, change the x:class property in xaml to be WindowTestCopy instead of WindowTest
  5. Open the code behind in WindowTestCopy, and change any references to WindowTest to WindowTestCopy
  6. Compile

Expected: no errors, the copy (clone) operation is successful

Actual: compile error "Cannot access non-static method 'InitializeComponent' in static context".

I have only this one error. Obviously InitializeComponent() is becoming an ambiguous reference, but it isn't clear to me how to make manual edits to the code to fix this. I wish that VS or Resharper would automatically assist me with this.

UPDATE

WindowTest contains two userControls that I had not mentioned previously. After the copy/paste occurs, for some reason the following xaml elements became malformed within WindowTestCopy:

xmlns:userControls....(ellided) xmlns:userControls....(ellided)

By deleting these, Resharper determined that the userControl objects were missing xmlns reference tags and asked me if I wanted to import them automatically. I selected yes. After Resharper added the missing xmlns reference tags I was able to compile (all errors disappeared).

I do not have an explanation for why this happened. In my steps to reproduce, I do not edit the xaml and it should therefore be identical to the originating xaml. This is curious behavior, but at least there is a workaround as stated.

Upvotes: 4

Views: 7451

Answers (6)

Miyamoto Musashi
Miyamoto Musashi

Reputation: 532

This easy way worked for me. The trick is to create a new folder nearby named, e.g., Scratch.

Then I was able to right-click on my subject Toy1.xaml file and choose Copy. Then go to Scratch folder and choose Paste. Then I could rename it to Toy2.xaml, and adjust .cs stuff as I wished.

Then I simply dragged Toy2 back to the appropriate folder, and deleted the Scratch folder.

Upvotes: 0

jakob.j
jakob.j

Reputation: 963

For me it turned out that it's easier outside Visual Studio, rather than in it:

  1. Close the solution in Visual Studio
  2. Open the solution folder with an external editor/IDE (e.g. VSCode)
  3. Do the copy of the .xaml and .xaml.cs files and directly do all required naming adjustments / text replacements in both files (old_window_name -> new_window_name, etc.)
  4. Make sure that none of the identifiers of the original window is present in the copied files anymore
  5. Save and close the folder in the external editor
  6. In Visual Studio, open the solution again

Upvotes: 0

RogerAguiar
RogerAguiar

Reputation: 1

I am going to show you in an easier way: I had this same issue that you did, this error occurs because you made a copy of the first form (or page in my case here), than you renamed the class and file to your new class, but look the following code:

<Page x:Class="Advocacy_Software.Pages.PageRegisterCustomer"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Advocacy_Software.Pages"
      mc:Ignorable="d" 
      d:DesignHeight="800" d:DesignWidth="800"
      Title="PageRegisterCustomer" Background="Lavender">

The first line: <Page x:Class="Advocacy_Software.Pages.PageRegisterCustomer" must be updated as well to <Page x:Class="Advocacy_Software.Pages.PageRegisterCustomerCopy".

That's all! I hope to have been helped!

Upvotes: 0

Rick Velde
Rick Velde

Reputation: 591

When it happened to me, it went like this:

  1. Copy the xaml in solution explorer.
  2. Rename the xaml in solution explorer.
  3. Rename the x:Class in the xaml.
  4. Rename the class name in the xaml.cs.
  5. Rename the constructor in the xaml.cs.
  6. Why is everything still broken? <== (you are here probably)
  7. Realize there is secret voodoo witchcraft underneath.
  8. Copy the contents of the xaml and the xaml.cs to a couple of notepads.
  9. Delete the xaml from solution explorer.
  10. Create a new xaml in the solution explorer with the name you wanted.
  11. Overwrite both the xaml and the xaml.cs with the exact contents of the two notepads.
  12. Errors are gone.

Upvotes: 5

DRapp
DRapp

Reputation: 48139

Someone else actually posted and then deleted had the correct idea, but brief on why.

The issue you were running into is due to a duplication of a class within the same project... even though in the solution explorer you can easily copy/paste a WPF form or any other class, user control class, etc. When copied, it suffixes the file names to " - Copy", and if you compile right away will fail. Reason being? In the class itself the class name and window name is the same. So, in the project you have TWO instances of the class and it is choking on that hoping for you to resolve the duplicates. I ran into this exact same thing early on in my WPF development.

So, now that I've explained WHY it is failing, here is what you would need to do, to correct the issue. I created a window in my sample project called "FirstWindowSample", so two files are created FirstWindowSample.xaml and FirstWindowSample.xaml.cs. The .cs version is the code-behind of the window (or user control class, the principle is EXACTLY the same.

If you look in the "FirstWindowSample.xaml" code (the visual-design version), the code will look something like...

<Window x:Class="YourProject.FirstWindowSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="FirstWindowSample" Height="300" Width="300">
    <Grid>

    </Grid>
</Window>

Notice in the first line

   x:Class="YourProject.FirstWindowSample"

You need to change the ".FirstWindowSample" to whatever you want for your new form such as

   x:Class="YourProject.SecondWindowSample"

Next, change over to the CODE-BEHIND file "FirstWindowSample.xaml.cs".

namespace YourProject
{
    /// <summary>
    /// Interaction logic for FirstWindowSample.xaml
    /// </summary>
    public partial class FirstWindowSample : Window
    {
        public FirstWindowSample()
        {
            InitializeComponent();
        }
    }
}

This is the hard-reference of the class name and its corresponding constructor. Just change these to match the new window name you are expecting (such as sample SecondWindowSample)

namespace YourProject
{
    /// <summary>
    /// Interaction logic for SecondWindowSample.xaml
    /// </summary>
    public partial class SecondWindowSample : Window
    {
        public SecondWindowSample()
        {
            InitializeComponent();
        }
    }
}

At the end your project will now have a completely different class name that is not duplicated and cause compile errors. The FIRST time you run into this, yeah... a pain to find out. Once you get it, the next 2-3 times are the "oh-yeah" refresher... After that you sort of do it without thinking about it.

Upvotes: 2

sapbucket
sapbucket

Reputation: 7195

The issue was resolved by deleting all xlmns elements in the xaml and letting resharper automatically add them back in. I am not satisfied with this solution because it is not logical; however, it did resolve the compile error.

Upvotes: 0

Related Questions