Archive for the “.NET” Category

Consider a Windows Phone 7 application with a textbox and an ApplicationButton.

TextBox and ApplicationButton

UI:

  1. <Canvas x:Name="ContentGrid" Grid.Row="1" Height="545" Width="480">
  2.     <TextBlock Text="Enter text here" Canvas.Left="6" Canvas.Top="187" />
  3.     <TextBox x:Name="myTextBox" Text="{Binding Test, Mode=TwoWay}" Height="69" Width="480" Canvas.Left="0" Canvas.Top="209" />
  4. </Canvas>

Backend:

  1. namespace WindowsPhoneApplication1
  2. {
  3.     using System;
  4.     using System.ComponentModel;
  5.     using System.Windows.Controls;
  6.     using Microsoft.Phone.Controls;
  7.  
  8.     public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
  9.     {
  10.         private string _test;
  11.         // Constructor
  12.         public MainPage()
  13.         {
  14.             this.InitializeComponent();
  15.  
  16.             this.DataContext = this;
  17.         }
  18.  
  19.         public string Test
  20.         {
  21.             get
  22.             {
  23.                 return this._test;
  24.             }
  25.             set
  26.             {
  27.                 if (value != this._test)
  28.                 {
  29.                     this._test = value;
  30.                     this.PropertyChanged(this, new PropertyChangedEventArgs("Test"));
  31.                 }
  32.             }
  33.         }
  34.  
  35.         #region INotifyPropertyChanged Members
  36.  
  37.         public event PropertyChangedEventHandler PropertyChanged;
  38.  
  39.         #endregion
  40.  
  41.     }
  42. }

The textbox is bound to a property on the backend (two way binding) and when you click the bottom button the text is saved/send/encrypted/whatever.

Now the problem is that clicking the button doesn’t do a UI –> source binding update as it would do with a normal button.

Testing the app

I enter the text ‘test’ on the TextBlock and IMMIDIATLY click the ApplicationButton. I don’t do anything else. This is a common user practice, he changes something and clicks the save/send/whatsoever button.

This is the result:

Visual Studio 2010 Watch 1

Check the Watch 1. As you can see the value is still null. The value is not sent to the _test value. How do we solve this?

You can add the following line to the click event handler:

  1. this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

So the result will look like this:

  1. private void AppbarButton1Click(object sender, EventArgs e)
  2. {
  3.     this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
  4.  
  5.     // handle save/send/encrypt/whatever here
  6. }

There are 3 downsides I think:

  1. You need to name your TextBlock which (I think) unnecessarily clutters your scope with otherwise unused variables (that’s why we use bindings too!)
  2. Your UI and ViewModel (in my case) aren’t decoupled 100% anymore. In Windows Phone 7 this is no issue though, since WP7 has no ICommand and I have to couply my UI and ViewModel anyway :)
  3. You need to remember to write this line! Which can be quite cumbersome with a lot of application buttons.

And items in a ApplicationBar.MenuItems (ApplicationBarMenuItem) have the same problem. The UI doesn’t push the update to the ViewModel.

I hope this will be fixed in the final version, and I will post this to Microsoft Connect. If anybody has a better solution please feel free to share it.

Comments No Comments »

  1. static class ExtensionMethods
  2. {
  3.     public static void Raise<TValue>(this PropertyChangedEventHandler handler, Expression<Func<TValue>> propertySelector)
  4.     {
  5.         var memberExpression = propertySelector.Body as MemberExpression;
  6.  
  7.         if (handler == null || memberExpression == null)
  8.         {
  9.             return;
  10.         }
  11.  
  12.         var sender = ((ConstantExpression)memberExpression.Expression).Value;
  13.         handler(sender, new PropertyChangedEventArgs(memberExpression.Member.Name));
  14.     }
  15. }

Use this as an extension method like this on a class that implements INotifyPropertyChanged

  1. class SomeClass : INotifyPropertyChanged
  2. {
  3.     private string _someProperty;
  4.  
  5.     public string SomeProperty
  6.     {
  7.         get
  8.         {
  9.             return this._someProperty;
  10.         }
  11.         set
  12.         {
  13.             if (value != this._someProperty)
  14.             {
  15.                 this._someProperty = value;
  16.                 this.PropertyChanged.Raise(() => this.SomeProperty);
  17.             }
  18.         }
  19.     }
  20.  
  21.     public event PropertyChangedEventHandler PropertyChanged;
  22. }

Good luck :)

-Kristof

Comments No Comments »

Since MvvmLight exposes it’s own ViewModelBase you cannot use this little script to raise the INotifyPropertyChangedEventHandler, because .NET doesn’t allow you to raise events in derived classes. This is because the compiler generates a private delegate (it’s in VB.NET but that doesn’t matter).

And since the ViewModelBase only exposes a protected RaiseProperty(string propertyName) I cannot use strongly typed reflection.

So I found some code, and rewrote it like this.

Now you can create a class that inherits from ViewModelBase, and make your ViewModels inherit from your just created class.

Now you have a pattern like this:

ViewModelBase <—DefaultViewModel <—MainPageViewModel

And your DefaultViewModel should look like this:

  1. public abstract class DefaultViewModel : ViewModelBase
  2. {
  3.     protected void RaisePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
  4.     {
  5.         var memberExpression = (propertySelector.Body as MemberExpression);
  6.  
  7.         if (null != memberExpression)
  8.         this.RaisePropertyChanged(memberExpression.Member.Name);
  9.     }
  10. }

And your MainPageViewModel (for example):

  1. public class MainPageViewModel : DefaultViewModel
  2. {
  3.     private decimal _remainingCredits;
  4.  
  5.     /// <summary>
  6.     /// Remaining credits of the current account
  7.     /// </summary>
  8.     public decimal RemainingCredits
  9.     {
  10.         get
  11.         {
  12.             return this._remainingCredits;
  13.         }
  14.  
  15.         set
  16.         {
  17.             if (this._remainingCredits != value)
  18.             {
  19.                 this._remainingCredits = value;
  20.  
  21.                 this.RaisePropertyChanged(() => RemainingCredits);
  22.             }
  23.         }
  24.     }
  25. }

You can use the form of RaisePropertyChanged(() => NameOfProperty);

This way, when you rename a variable in your code the refactor engine picks it up and renames it accordingly. (it forget strings :)

Good luck,

Kristof

Comments No Comments »

Hi all,

I sometimes get this error when I forget that controls cannot be accessed across threads:

Cross-thread operation not valid: Control 'someLabel' accessed from a thread other than the thread it was created on.

What many people do is this:

  1. private void UpdateLabel(string text)
  2. {
  3.     this.Invoke(new Action(() => this.someLabel.Text = text));
  4. }

This is not the right pattern. You don’t always HAVE to invoke. You are better off by checking if you have to invoke it on the underlying thread, and if not, just execute it directly. It’s all about correctness :)

The right pattern would be:

 

  1. private void UpdateLabel(string text)
  2. {
  3.     if(this.InvokeRequired)
  4.     {
  5.         this.Invoke(new Action(() => this.UpdateLabel(text)));
  6.         return;
  7.     }
  8.  
  9.     this.someLabel.Text = text;
  10. }

Use Control.InvokeRequired :)

Good luck

-Kristof

Comments No Comments »

In my last project I had the assignment to create a client server application. Not that hard. We chose to use WCF for the communication itself, because that was easy, straightforward and well supported with .NET 3.5SP1 (and Visual Studio 2008 of course).

As we didn’t have the time to create our own mapper to map the database to code, nor did we have time to study another mapper (nHibernate came to the question) we choose for something we already knew. LINQ 2 SQL.

Now we all used it in a connected environment. But as you all know, WCF is not connected. The DataContext is lost upon transmitting the entity to the client.

Now that’s the problem, change tracking is lost and LINQ 2 SQL doesn’t play well with reattaching detached entities.

Transmitting an entity from server to the client was no problem, with the DataContext.LoadOptions we were able to eager load all the entities required and transmit them to the client. And we didn’t want to use a third party template or baseclass because those weren’t approved by management :) .

In order to make LINQ to SQL add DataMember and DataContract properties to your classes you need to set the Serialization Mode to Unidirectional (as shown below):

Serialization Mode: Unidirectional

In code you can now see attributes like this:

DataMemberAttribute

and this:

DataContractAttribute

But the DataMemberAttribute is not applied on EntityRef, only EntitySet.

EntityRef is used to lazy-load a reference to 1 entity. EntitySet is used for a list of lazy-loadable entities.

Let me explain with an example (I’m using the Northwind database).

A Product has 1 category and a Category has multiple Products.

This means that a Category has an EntitySet<Product> (as shown below, notice the DataMemberAttribute):

Category -> EntitySet<Product>

While a Product has only 1 Category (notice the absence of the DataMemberAttribute):

image

When working in a connected environment the absence of those attributes is not a problem. But on WCF it is. Since you cannot do lazy loading when the entity is transmitted to the client you need to make sure you load everything in front.

While you can create DataLoadOptions for a Product.Category link the absence of the DataMemberAttribute prevents the WCF serializer from serializing the Category Entity.

  1. using (NorthwindDataContext northwindDataContext = new NorthwindDataContext())
  2. {
  3.     var dataLoadOptions = new DataLoadOptions();
  4.  
  5.     dataLoadOptions.LoadWith<Product>(p => p.Category);
  6.  
  7.     northwindDataContext.LoadOptions = dataLoadOptions;
  8.  
  9.     return northwindDataContext.Products.Where(p => p.ProductID == 1).SingleOrDefault();
  10. }

When invoking this method on the client you will see that the received Product’s Category is null.

First of all: why is there no DataMemberAttribute on the EntityRef in LINQ2SQL?

Imagine me having a Category, and eager (opposite of lazy) loading all the Product entities. All those products have 1 category, and they if I set the Product.Category to eager load… think about it, this will cause an infinite loop:

Category –> x Products, for each of those products load their category, for each of those categories, load their products and so on.

Boom, the WCF XML serializer cannot handle this.

How do we solve this?

In the LINQ2SQL designer take the Product.Category (or Category.Products if you will) link, and set the Child Property to false.

Child Property

This will remove the Category.Products property and generate a DataMemberAttribute on the Product.Category. Of course now you cannot get all the products in a category through a Category link this:

Category.Products is now gone

But you have to do something like this:

The right way, through the foreign key

This generates the same SQL statement on the backend and now you can properly sent those entities to your client.

Signing off,

Kristof

Comments 1 Comment »

Hi all,

I tried to display an icon in my Windows Phone 7 application:

<shell:ApplicationBarIconButton x:Name="appbar_button1" IconUri="/Images/appbar.feature.settings.rest.png" Text="Settings" />

By default, when you add an image to the solution folder it sets the build action as Resource, as shown below:

Build Action Resource

But when you run the application with the Build Action as Resource you will get a result looking like this:

Wrong icon

While I really meant an icon looking like this:

Gear

How do we fix it?

Set the Build Action to Content!

Build Action Content

And this is the result:

Result

Comments No Comments »

There seems to be a problem with the default keyboard mapping of the so called ‘Align Assignments’ found in the Visual Studio 2010 Pro Power Tools.

The default shortcut is mapped to Control + Alt + ]. While this is not a problem on a QWERTY these keystrokes are used to type a square bracket on a AZERTY keyboard:

Azerty keyboard

As you can see the character on the lower right corner needs to be accessed with Ctrl + Alt + key or the Alt Gr + key. This way you trigger the ‘Edit.AlignAssignments’ on your keyboard. Thus the ‘]’ doesn’t appears on screen, it merely aligns the current line.

Edit.AlignAssignments shortcut

Solution: remove or remap the shortcut.

Thanks to Gill Cleeren for pointing out this problem.

Comments No Comments »

I’ve been stuck on this for a few days.

At the moment, Firefox 3.6.4 (and newer) have a new functionality called ‘Crash protection’, which is quite nice.

For customers.

It now runs the plugins in a separate process called ‘plugin-container.exe’ (look in your task manager).

Task manager plugin-container.exe

But for developers it’s quite the hassle, since Visual Studio attaches itself to Firefox but NOT to this process. So no more Silverlight debugging for you!

Luckily there are two options for you!

The first option is the most straight forward, but has to be done each time. Use Visual Studio to attach itself to plugin-container.exe, refresh the website, and BAM, you’re up and running!

Attach to Process

On the next screen click ‘plugin-container.exe’. There might be 2, if so, select the one with ‘Silverlight’ in the ‘Type’ column:

Attach to Process Window

And hit ‘Attach’.

While this solution is adequate for when you need to debug it one time at a day, but for me, I only debug in Firefox, and when necessary I use Internet Explorer. For that you can go to your ‘about:config’ in Firefox, disable ‘dom.ipc.plugins.enabled.npctrl.dll’ (set it to false).

Comments 1 Comment »

Since I’m still working on a VB.NET I start to understand the language more and more. It feels like working with PHP. There are so many hacks, many things happen without you knowing that it happens.

Consider the following classes defined:

class Foo {}
class Bar : Foo
{
    internal static Foo GetInstance()
    {
        return new Bar();
    }
}

In C# you would have:

Console.WriteLine(Bar.GetInstance() as Bar);

the ‘as’ operator tries to cast foo to an instance of Bar. If that doesn’t succeed it returns null.

The code gets compiled to something like this:

{
    Foo __foo = Bar.GetInstance();
    Console.WriteLine(__foo is Bar ? (Bar)__foo : (Bar)null);
}

Doing a cast:

Console.WriteLine((Bar)Bar.GetInstance());

Throws an exception if we cannot cast. So you need to do a try catch around it.

Those are the casting operators in C#.

VB.NET has a little bit more stuff.

I will list them briefly:

CType(obj, Type), DirectCast(obj, Type), TryCast(obj, Type) and some predefined functions like CBool, CStr, Cint.

DirectCast(obj, Type) is the equivalent of the (Type)obj. No problem. TryCast(obj, Type) is the equivalent of obj as Type. No problem either. The problem arrises when we use CType and or one of those predefined functions.

You’d expect CBool(obj) to result in (you cannot do TryCast on a valuetype, hence the DirectCast) DirectCast(obj, Boolean). But no.

Consider the following code:

Dim boolTest As Object = False
Console.WriteLine(CBool(boolTest))

When compiled it gets converted to this:

Dim boolTest As Object
boolTest = CBool(0)
Console.WriteLine(Conversions.ToBoolean(boolTest))

You can take a look at the Conversions class with Reflector. It’s located in the Microsoft.VisualBasic dll (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.VisualBasic.dll) and the full name is Microsoft.VisualBasic.CompilerServices.Conversions.

Reflector Visual Basic

CBool should just try a DirectCast in my opinion.

But CType has some more nuisances. We are still using the Foo and Bar classes defined above.

Consider this code:

Dim foo As Foo = Bar.GetInstance()
Console.WriteLine(CType(foo, Bar))

Gets compiled to:

Dim foo As Foo
Console.WriteLine(DirectCast(Bar.GetInstance, Bar))

Great, it uses DirectCast. So if the conversion fails it throws an exception…

Now the catch:

Dim test As Object = String.Empty
Console.WriteLine(CType(test, String))

You’d EXPECT it to do a DirectCast but no, this is what gets emmited:

Dim test As Object
Console.WriteLine(Conversions.ToString(String.Empty))

Again a roundtrip you don’t see…

That’s why I don’t like VB.NET. Too much happens behind the screens.

I know that you can program VB.NET without all of this (use DirectCast and TryCast yourself). But the problem is that all legacy developers use these functions because they don’t know better.

I wish these features where deprecated and only available for projects converted from VB6 code.

Comments No Comments »

I ran into this little problem last week. I had a class with some properties and they were implemented like this:

class Foo
{
    private int _bar;

    public int Bar
    {
        get
        {
            return this._bar;
        }
        set
        {
            this._bar = value;
            this.DoSomeThing();
        }
    }

    private void DoSomeThing()
    {
        /* blah */
    }
}

Setting the value of Bar to something triggers DoSomeThing, whether the value of _bar is changed or not. (setting _bar to 5 when it is 5 will still trigger DoSomeThing, for example a UI refresh).

You can avoid this by doing this in your property:

class Foo
{
    private int _bar;

    public int Bar
    {
        get
        {
            return this._bar;
        }
        set
        {
            if (this._bar != value)
            {
                this._bar = value;
                DoSomeThing();
            }
        }
    }

    private void DoSomeThing()
    {
        /* blah */
    }
}

This makes sure that you don’t execute the value when the value hasn’t changed.

This occurs in particular in Excel when trying to update the CurrentPageName of a DataField in a PivotTable. I need to check if the value has changed, and then, if it has changed, assign it.

Comments No Comments »

And shepherds we shall be, for thee my Lord for thee, power hath descended forth from thy hand, that our feet may swiftly carry out thy command. We shall flow a river forth to thee, and teeming with souls shall it ever be. In nomine Patris, et Filii, et Spiritus Sancti.