Growing memory allocation as WPF application navigates - c#

I am building a WPF application and have been trying to implement opening a new page when a button is clicked.
The button is in the page MainPage and it opens the page SafetySettings. There is then a button in the SafetySettings page which opens the MainPage.
The only way I have been able to open the pages successfully is with the following:
private void btnTest_Click(object sender, RoutedEventArgs e)
{
SafetySettings safety = new SafetySettings();
this.Frame.Navigate(typeof(SafetySettings),safety);
}
This works as desired but I noticed the memory allocation of the program continuously increases as I swap between the pages. I think I am not implementing this correctly but I could not figure out another way to open a new page from the current page.
MainPage.xaml.cs
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace DataAcquisitionGUI
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void btnTest_Click(object sender, RoutedEventArgs e)
{
SafetySettings safety = new SafetySettings();
this.Frame.Content = null;
this.Frame.Navigate(typeof(SafetySettings),safety);
}
}
}

Your memory allocation is growing cause you create SafetySettings new each time you click the button and I think you do not dispose the item correctly so there is no clean-up.
Implement the IDisposable interface in your SafetySettings or create a method which "destroys" the instance of your class. This helps you to keep your application clean of unused resources!

Related

Execute code after reloading page on Navigation.GoBack()

I have a Window that only has one frame to show the different pages that my application has.
When a Page loads, it initializes several threads that deal with different elements of the UI. When I change the page with frame.Navigate(new NextPage()) I abort those threads, as it doesn't make sense to keep them running when the page is not in the foreground.
The problem comes when I make frame.GoBack(), since I have no way to relaunch those treads on the page because no code is executed when I return to the page.
There is something similar to the OnPause, OnStart, OnStop method of Android but for WPF and pages?
Something like the following:
public MainPage()
{
InitializeComponent();
var thread = new Thread(() => Code());
thread.Start();
}
public Code()
{
// Do Stuff
}
public Continue()
{
thread.abort()
frame.Navigate(new NextPage())
}
public OnPageReloaded()
{
thread.start()
}
You should look into the Task Parallel Library (TPL) and create tasks instead of threads. Calling Abort() on a thread is bad practice.
As to your actual question, you could initialize your work in the Loaded event handler of the Page instead of doing it in the constructor:
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
Loaded += Page1_Loaded;
}
private void Page1_Loaded(object sender, RoutedEventArgs e)
{
//start your tasks here...
}
}
The Loaded event will be invoked each time your Page instance is being navigated to. There is also an Unloaded event that you can use to do cleanup.

Syncing data between two Window in WPF

I am developing an application in WPF. I need to load an instance of the Window class (which I call Win1 here) with which a form is filled. Then, when the Submit button is clicked, Win1 closes and only then can a new Win2 window be loaded (another class, also inherited from Window). The problem is that both of them open and I can not synchronize the data obtained from the first Win1 and pass them to the second Win2. I'm just messing up.
Someone can give me a generic idea indicating the tools and the pattern I need to do the above. For the specifications given to me, it is necessary that Win2 appears only after Win1 has finished its work.
Even though the application is more complex than I described it now, I would like to post some code, but I manage to confuse the ideas of who is reading me, so I tell you that at the moment I'm managing the windows inside the constructor of App.cs, while MainWindow.cs corresponds to Win2 and I created a new class to implement Win1.
public partial class App : Application
{
// Params...
public App()
{
Client = LoadNetwork();
User = LoadUser(Client); // Shows Win1
Games = LoadMinigames();
mainWindow = new MainWindow(User, Games);
Application.Current.MainWindow = mainWindow; // On XAML default is Hidden
mainWindow.Show(); // Shows Win2
}
// Other methods...
}
The biggest problem for me is to pass User data to MainWindow and I do not have many ideas on how to deal with this case.
Update
public partial class MainWindow : Window
{
public UserLoading ul;
public UserRegistering ur;
public User.UserProfile User;
private List<Game.Game> Games;
public Label Username;
public MainWindow(User.UserProfile user, List<Game.Game> games)
{
User = new UserProfile();
InitializeComponent();
User = user;
Games = games;
Username.Content = User.Username;
DrawList(Games);
}
//...
}
I realize I have explained myself a bit 'badly rereading my question several times. So I update it trying to be clearer by reporting here my answer to one of the comments.
The UserLoad method is not blocking, because inside it are instantiated classes that inherit Window (other windows for login and registration in other words) then the flow of execution proceeds and instantiates the MainWindow where naturally the argument "user" will result null because the forms have not been filled yet. I realize now that perhaps I had explained myself badly. The call of Win1 is not blocking and I would like it to return only when the user data is ready to be passed as an argument to Win2.
I have done this in the past. here is my solution:
Set Your Launch Window to Win1. Let It launch. Create a Static Method in App.cs to launch Win2. When Win1 is ok to shut down and you want Win2 to open call App.ShowMainWindow(this) from within Win1.
App.cs
public partial class App : Application
{
static internal void ShowWin2(Win1 win1)
{
Win2 win2 = new Win2();
// Copy Win1 stuff to Win2 here
Application.Current.MainWindow = win2;
win2.Show();
}
}
Win1
public partial class Win1 : Window
{
public Win1()
{
InitializeComponent();
}
private void CloseAndLaunchWin2()
{
App.ShowWin2(this);
this.Close();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
CloseAndLaunchWin2();
}
}
As User Nawed mentioned, you should read into MVVM. Syncing can be achieved by using the same model for two different views.
You could do something like this.
var sharedContext = new MyViewModel();
var viewOne = new MyWindow();
var viewTwo = new MyUserControl();
viewOne.DataContext = viewTwo.DataContext = sharedContext;

Different Navigation Types Between Pages

I am trying to make an app with a Main Page that is a plain Content Page (i.e. no toolbar) which has a button that leads into a Navigation Page (with toolbar). I'm struggling to find any resources to help me out in this specific case.
I have tried the following. In my App.xaml:
public partial class App : Application
{
public App ()
{
InitializeComponent();
MainPage = new App5.MainPage();
Pallets = new NavigationPage(new Pallets()); //Error: 'Pallets' is a type but is used like a variable
}
...
}
Above is the error I get on Pallets. I could change Pallets for MainPage and write the whole app with Navigation pages, which I will do for now, but I would prefer not to.
In my MainPage.xaml.cs, I'm trying to switch the view when the button is clicked:
public partial class MainPage : ContentPage
{
...
async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new Pallets());
}
}
I have seen examples such as this that include Navigation Page to Navigation Page buttons, but not plain Content Page to Navigation Page buttons.

Wpf dll user control window not showing when called from an exe application

I have a WPF Menu application wich calls a WPF User Control dll and the dll window is not showing. The dll does not require parameters and its window have only one button. I added a MessageBox to the dll code to check if it is being loaded and it does, but the window does not show.
I'm using VS 2015. The dll project named Empresa.Reg was created using C# Windows Classic Desktop WPF User Control (There is no C# Windows WPF User Control selection), it is referenced in the Menu project and its ouput is Class Library. Menu project named MenuDePruebas Ouput is Windows Application. Any help would be appreciated.
This is the Menu exe code:
....
using System.Windows;
using Empresa.Reg;
namespace MenuDePruebas
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnRegEmpresa_Click(object sender, RoutedEventArgs e)
{
UserControl1 algo = new UserControl1();
}
}
}
And this is the WPF User Control dll code:
....
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Empresa.Reg
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
MessageBox.Show("Testing"); // This line works as expected
}
private void button_Click(object sender, RoutedEventArgs e)
{
}
}
}
I think I've found a solution creating a new window for the dll user control in the menu exe as follows, something I thought was an automatic thing. If there is a better solution I appreciate letting me know. Thanks.
private void BtnRegEmpresa_Click(object sender, RoutedEventArgs e)
{
Window UserControlNewWindow = new Window
{
Title = "Some Title", Content = new UserControl1()
};
UserControlNewWindow.ShowDialog();
}
One simple way:
in ur xaml of the Window add a ContentControl
as u click the menu put corresponding usercontrol in the contentcontrol
<ContentControl x:Name="CntUsercontrol"/>
In code behind
CntUserControl.Content = new UserControl();
If you use MVVM the you can switch the views based on the viewmodel using a DataTemplate.
Hope this helps

Custom Page Class w/ automated unload Event

we have a rather large Silverlight application and we need to add some extra functionality to it.
The App consists of an Frame-Element and a TreeView w/ HyperlinkButtons for the navigation. Every content which will be loaded into the main Frame is a Page.
Now, I need to hook into every Page's unload event. Currently we use something like this:
/* PageX.xaml */
<navigation:Page
x:Class="Foo.Views.PageX"
<!-- namespacing -->
Title="Test Page X"
Unloaded="Page_Unloaded">
...
</navigation:Page>
Code-behind:
/* PageX.xaml.cs */
/* usings */
namespace Foo.Views
{
public partial class PageX : Page
{
public PageX() {
InitializeComponent();
}
private void Page_Unloaded(object sender, RoutedEventArgs e) {
/* CODE */
}
}
}
This approach need to be implemented on each and every Page, as the code within the unloaded method stays exactly the same... As I mentioned earlier, we have a couple of Pages and it would be much more useful to create a custom Page-class where this Page_Unloaded() is implemented directly, so that we don't need to alter every Page.
Can you please tell me how to create such a custom Page-class?
Thanks in advance for any help!!
Kind regards!
You could create a base Page class that all your pages inherit from which registers the event in the constructor...
public class BasePage : Page
{
public BasePage()
{
Unloaded += Page_Unloaded;
}
void Page_Unloaded(object sender, RoutedEventArgs e)
{
}
}
Then all your pages could inherit from that...
public partial class Page1 : BasePage
{
public Page1()
{
InitializeComponent();
}
}
...and in the xaml of each page...
<base:BasePage x:Class="WPFApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:WPFApp">
<Grid>
</Grid>
</base:BasePage>

Categories

Resources