Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

C# and .NET Tips and Tricks

Quests in programming in .NET

Παρουσίαση με Ετικέτες

Όλες οι Ετικέτε... » WPF   (RSS)
A simple way to detect memory leaks in C# and how to create one with events :)

In this post we will see a simple code fragment that can be used to detect memory leaks (more specific objects that are not cleaned by the garbage collector) and we will do it in the context of an interesting memory leak that can be created when using event delegates.

The memory leak with event delegates

Suppose you have an application in WPF with a single window that presents some money values in a specific currency (say EURO). At a specific instance you may have more than one such windows open.

Now a requirement comes that defines that you need to be able to change the currency (say from euro to dollar) and have this change be reflected immediately to any currently open window displaying the money value. One easy way to tackle this is shown in the following figure:

The "settings" object is static with a static property "Currency" with the current currency and an event called "OnCurrencyChanged" that is fired when the currency is changed. The "Window" class ("window1" nad "window2" objects) defines a method "currencyChanged". When a window is opened it attaches the "currencyChanged" method to the "OnCurrencyChanged" event. This method will be called whenever the event is fired and will be responsible for converting the money values in the windows. Let's see some code for that. First the "settings" class:

public static class settings
{
    public static event Action OnCurrencyChanged;

    public static void ChangeCurrency(string newCurrency)
    {
        //...
        if (OnCurrencyChanged != null)
            OnCurrencyChanged(newCurrency);
    }

}				

The code for the window with the money values has the "currencyChanged" method:

public partial class MoneyWindow : Window
{
    public MoneyWindow()
    {
        InitializeComponent();
    }

    public void currencyChanged(string newCurrency)
    {
        // Change the view to reflect the change here
    }
}				

The initializer of the window with the money values will be as follows:

MoneyWindow dlg = new MoneyWindow();
dlg.Show();
settings.OnCurrencyChanged += dlg.currencyChanged;	

Which in other words defines that when the window is created it will be listening to the "OnCurrencyChanged" event.

And you have your memory leak right there! Even if you close the window in some time, the event you have attached still keeps it "connected" to your application and therefore it will never be garbage collected. Just for a reminder, the objects are destroyed by the garbage collector when there are no other objects pointing to them. But in this case you have an "implicit" connection with the event. If you execute the demo application (here) you will see that opening and closing the window keeps consuming more and more memory which never gets freed (it helps to have the "Task Manager" open to test that). The solution is simple and it just requires you to unsubscribe from the event with "-=" when the window is closed. But say you are in a large application you are not sure whether an object gets garbage collected or not and wanna check that then what can you do?.

Detecting memory leaks

Or better checking whether an object will get garbage collected. Implement in your project a class like the following:

public static class MemoryLeak
{
    public static WeakReference Reference { get; private set; }

    public static void CheckObject(object ObjToCheck)
    {
        MemoryLeak.Reference = new WeakReference(ObjToCheck);
    }

    public static void IsItDead()
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        if (MemoryLeak.Reference.IsAlive)
            Debug.WriteLine("Still here");
        else
            Debug.WriteLine("I 'm dead");
    }
}				

The code creates a weak reference to an object. The "weak reference" means that while it keeps a reference to the object this does not prevent the garbage collector from cleaning it (in other words this reference does not count in terms of collecting the object when not referenced). So we create the reference and then by calling "IsItDead" we just force the GC to collect any unneeded objects. If the object in question still persists then we have a memory leak.

For our example above, when we create the window we create a weak reference to the window object. Then we create a button that calls the "IsItDead" method. If we do not have a memory leak then the method should return "Still here" while the window is open and "I 'm dead" a while after the window is closed.

You can download the demo project here

Posted: Κυριακή, 26 Μαΐου 2013 5:31 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Porting a WPF application to Windows8

That is, our class implements the INotifyPropertyChanged interface and also raises the notification for the “Description” property whenever the Id or the Name properties are changed in order for the Listbox contents (databound to Description) to be refreshed. Our ViewModel for the application is as follows:

 

public class MainWindowViewModel : INotifyPropertyChanged
{
   private List<Client> _clients;
   public List<Client> Clients
   {
      get { return _clients; }
      set { _clients = value; 
         if (PropertyChanged != null) 
             PropertyChanged(this, new PropertyChangedEventArgs("Clients")); }
    }
    private Client _selectedClient;
    public Client SelectedClient
    {
       get { return _selectedClient; }
       set { _selectedClient = value; 
          if (PropertyChanged != null) 
              PropertyChanged(this, new PropertyChangedEventArgs("SelectedClient")); }
     }
     public MainWindowViewModel() {}
     public void Validate() {
        if (SelectedClient != null) {
           if (String.IsNullOrWhiteSpace(SelectedClient.Name))
              MessageBox.Show("Name cannot be empty for client");
           else
              MessageBox.Show("All ok");
        }
     }
     public event PropertyChangedEventHandler PropertyChanged;
}

 

Again, the ViewModel implementes the INotifyPropertyChanged interface and has the Clients property which will be databound to the ItemSource of the Listbox and the SelectedClient property which will be databound to the SelectedItem of the Listbox and to the detail Textboxes at the bottom of the window. Moreover, it provides the Validate method for validating the results. The XAML file describing the UI of the window is as follows:

 

<Window x:Class="AskADev.Article1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Demo WPF porting to Windows8" Height="400" Width="544" Loaded="Window_Loaded">
    <DockPanel>
        <Canvas DockPanel.Dock="Bottom" Height="100" Background="Beige">
            <TextBlock Text="Id" Canvas.Left="6" Canvas.Top="12" />
            <TextBox Text="{Binding SelectedClient.Id}" Canvas.Left="79" 
                                                        Canvas.Top="9" Width="72" />
            <TextBlock Text="Name" Canvas.Left="6" Canvas.Top="40" />
            <TextBox Text="{Binding SelectedClient.Name}" Canvas.Left="79" 
                                                          Canvas.Top="37" Width="311" />
            <Button x:Name="ButtonSubmit" Height="31" Width="73" Canvas.Left="443" 
                   Canvas.Top="63" Click="ButtonSubmit_Click">Validate</Button>
        </Canvas>
        <ListBox DockPanel.Dock="Top" ItemsSource="{Binding Clients}" 
                 SelectedItem="{Binding SelectedClient}" DisplayMemberPath="Description"/>
    </DockPanel>
</Window>

 

Where you can see the data bound properties. Finally the XAML.cs file initializes the ViewModel, attaches it to the DataContext and also provides the event handler for the button:

 

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    ViewModel = new MainWindowViewModel();
    DataContext = ViewModel;
}
private void ButtonSubmit_Click(object sender, RoutedEventArgs e)
{
   ViewModel.Validate();
}
 

We compile this and run it on a Windows7 machine and it runs correctly. Now we start the Windows8 Virtual Machine (instructions on how to install Windows8 on your desktop can be found in this post), get the executable we have created and run it on Windows8 “as is”:

image

Obviously, as expected, the application runs without any problems. But it runs on “Desktop” mode, while we want to make it run on the nice new Metro-Style UI. We open Visual Studio 2011 from within Window8 and select New Project/Templates/Visual C#/Windows Metro Style/Application:

image

The windows in this project template are more “Silverlight” like having as their root content a UserControl and not a Window. Therefore we leave the root declaration intact and copy/paste the inner contents of the original XAML.cs file. The changes we need to make are as follows (all changes are characterized as major/moderate/minor based on the time it will take you to make the changes in a full blown WPF app):

 

  • 1 (moderate) The Window must be converted to UserControl.
  • 2 (major) The “Dockpanel” is not supported (which is kinda expected since we will have a fixed size full screen application) and therefore we change it to a “Canvas” layout.
  • 3 (major) The default mode for the binding in now “One Way”. Therefore we need to specify the binding explicitly to “TwoWay”.
  • 4 (major) Textboxes get enlarged in the new “Metro” style (since they are intended for touch UIs) therefore we need to increase the spacing between the Textboxes (add approximately 10pixels). Of course if we had initially used a Stackpanel for the placement of our controls this would not be needed (good design always handles change more easily Smile)
  • 5 (minor) We need to change the colors to reflect the new style (I chose darker shades)

 

The new XAML is as follows (changes in yellow):

 

<UserControl x:Class="AskADev.Article1.Windows8.MainPage"
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Loaded="Window_Loaded"
    d:DesignHeight="768" d:DesignWidth="1366">

    <Canvas>
        <Canvas Canvas.Top="668" Width="1366" Height="100">
            <TextBlock Text="Id" Canvas.Left="6" Canvas.Top="12" />
            <TextBox Text="{Binding SelectedClient.Id,Mode=TwoWay}" 
                     Canvas.Left="79" Canvas.Top="9" Width="72" />
            <TextBlock Text="Name" Canvas.Left="6" Canvas.Top="50" />
            <TextBox Text="{Binding SelectedClient.Name,Mode=TwoWay}" 
                     Canvas.Left="79" Canvas.Top="47" Width="311" />
            <Button x:Name="ButtonSubmit" Height="31" Width="73" Canvas.Left="443" 
                    Canvas.Top="63" Click="ButtonSubmit_Click">Validate</Button>
        </Canvas>
        <ListBox Background="Black" Foreground="White" Width="1366" Height="668" 
                 ItemsSource="{Binding Clients}" 
                 SelectedItem="{Binding SelectedClient,Mode=TwoWay}" 
                 DisplayMemberPath="Description"/>
    </Canvas>
</UserControl>
 

The XAML.CS file (apart from some minor changes in the name) remains the same.

Finally, the ViewModel’s file is added as is to the application. The issues that we encounter here are the following:

 

  • 6 (major) The MessageBox is not supported. Therefore you will need to find another way to inform your users about the result (probably from within a special place of the UI). In this app we will just comment it out and do nothing. In real life we would have to change the UI to have a “Messages” area.
  • 7 (minor – but annoying until you discover it) Your application will compile if you leave the INotifyPropertyChanged interface to be defined in the System.ComponentModel assembly as it is for WPF. But the binding will not work! You need to replace the “using System.ComponentModel” statement with “using Windows.Ui.Xaml.Data” which also defines the INotifyPropertyChanged interface and the bindings will magically work!

 

We recompile and run the up and we are in “Metro”!

image

 

Shout it

Posted: Τετάρτη, 19 Οκτωβρίου 2011 6:18 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
ListBoxes with DataBound Images in WPF
In this post, we see how we can add a DataBound image in the DataTemplate of a WPF ListBox. We experiment with three different approaches of achieving that and discuss on which one to use depending on the situation. In all cases, the image files are embedded within the application as “Resource” files. Later in this post, we will see what needs to be changed in order to support having the image files in a folder outside of the application Assembly. Our object for binding will be the class named Item having the following properties: public class Item { public int PictureID { get ; set ; } public string Name { get ; set ; } } We want to display a specific image depending on the value of the property PictureID. The ListBox in the .xaml file be: < ListBox ItemTemplate ="{ DynamicResource DataTemplateItem }" ItemsSource ="{ Binding Items }" /> The definition of the DataTemplate for the items of the ListBox is: < DataTemplate x : Key ="DataTemplateItem"> < Canvas

Διαβάστε περισσότερα »

Posted: Τετάρτη, 12 Ιανουαρίου 2011 9:19 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
Entity Framework, the Context, ComboBoxes and Include Foreign Key columns.
How do they all connect? Well it boils down to the following questions: If I am using Entity Framework in a Desktop application when should I open the Context and for how long should I keep it open? I have ComboBoxes that will be used to select values for the Reference Properties of my Entity Framework objects. How am I going to achieve this? Should I bind to Reference Properties or should I include the Foreign Keys in my model (option named “Include Foreign Key columns in the model”) and bind to

Διαβάστε περισσότερα »

Posted: Πέμπτη, 9 Σεπτεμβρίου 2010 7:48 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Autosuggest Textbox for WPF
Here is an implementation of a nice Textbox in WPF that suggests possible values based on the current user’s input. It is different from WPF’s native editable Combobox since it does not load all possible values at initialization (saving time and memory). The Textbox calls a method that returns the suggested values as soon as it detects a specific amount of idle time in the user’s typing. This method will probably access the database using the value entered so far in the Textbox as the criterion

Διαβάστε περισσότερα »

Posted: Πέμπτη, 1 Ιουλίου 2010 7:57 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
Going from Model-View-Presenter to MV-VM with WPF Commands (Part #3: MVVM and Commands)
In previous posts ( Part 1 and Part2 ) I have presented the implementation of a toy application using the Model-View-Presenter pattern and Routed Commands. In this final post, I will present the migration to MVVM. In Part2 , we have reached a point where we have managed to partly centralize the logic that is needed to be implemented for each Command but we were not yet fully satisfied with the wiring that needed to be done in the code-behind file. So, we will try to tackle this problem: Approach #4 Our first

Διαβάστε περισσότερα »

Posted: Δευτέρα, 12 Οκτωβρίου 2009 8:44 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
Going from Model-View-Presenter to MV-VM with WPF Commands (Part #2: Commands with MVP)
In my previous post , I have presented the first two approaches for implementing the GUI and the logic of a toy application: Approach #1: All the logic in the code behind file. Approach #2: The Model-View-Presenter pattern. In this post, we will pick up from where we stopped, in our route to migrate to the benefits of the MVVM model and the use of Commands. It is recommended to take a look at the previous post in order to get an idea of the application and the two previous approaches) Approach #3: A hybrid MVP

Διαβάστε περισσότερα »

Posted: Δευτέρα, 12 Οκτωβρίου 2009 8:25 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
Going from Model-View-Presenter to MV-VM with WPF Commands (Part #1: MVP)
In this post I will try to show the application of the MVP and MV-VM programming approaches and the use of WPF commands in them. I will start with a simple Window in WPF with all the code intertwined in the code-behind file and transform it to a Window with no code at all at the code-behind file, showing the separation between the view and the logic that is achieved with MV-VM and Commands. The Window is the following: The "Add Client" adds a new client, the "Delete Client" removes the selected

Διαβάστε περισσότερα »

Posted: Τρίτη, 6 Οκτωβρίου 2009 9:01 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
WPF Designer Error "Could not create an instance of type"
Suppose that in a WPF application there are some custom User Controls implemented. During development in some windows that use the custom User Control you may find that the designer cannot load them and instead it gives the following error: "Could not create an instance of type YOURCONTROLHERE" This happens because the designer runs the constructor for the User Control whenever it needs to display it in design mode. Within the constructor something throws an exception. Sometimes this does not mean

Διαβάστε περισσότερα »

Posted: Κυριακή, 20 Σεπτεμβρίου 2009 10:48 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
NHibernate, PropertyChanged event and WPF
A typical implementation of an entity that supports the INotifyPropertyChanged interface for WPF Binding is for example as follows: public class Detail:INotifyPropertyChanged { private long _iD; public virtual long ID { get { return _iD; } set { _iD = value ; if (PropertyChanged != null ) PropertyChanged( this , new PropertyChangedEventArgs("ID"));} } private string _line1; public virtual string Line1 { get { return _line1; } set { _line1 = value ; if (PropertyChanged != null ) PropertyChanged( this

Διαβάστε περισσότερα »

Posted: Παρασκευή, 28 Αυγούστου 2009 4:30 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Timers in WPF
There are times when you need a task to execute periodically. There are two ways of achieving this: Use the System.Windows.Threading. DispatcherTimer Use the System.Threading. Timer Say now that you want to implement a class the executes DoSomething() periodically and also informs through a delegate to whoever listens whent the execution is performed. The class for DispatcherTimer is as follows: public class DTimer { private DispatcherTimer timer; public event Action < int > DoSomething; private int _timesCalled

Διαβάστε περισσότερα »

Posted: Παρασκευή, 31 Ιουλίου 2009 8:44 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Instantiating a class written in XAML from code.
There are some times when you want to write a specific framgent of the UI in XAML and then intantiate it in a code-behind file. This can also lead to the strange situation of being able to change the UI design completely afer the application has been compiled and shipped. Here is how such thing can be done: Suppose that you have written the following XAML code: < StackPanel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns : x ="http://schemas.microsoft.com/winfx/2006/xaml"

Διαβάστε περισσότερα »

Posted: Παρασκευή, 17 Απριλίου 2009 3:14 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: