Thursday, December 17, 2009

Detecting Design Mode in WPF controls

Who would've thought that it would be difficult to find information on detecting Design mode in WPF controls.  In Winforms, there is a simple DesignMode boolean property you can check, but it's not so obvious in WPF, plus Bing searches gave convoluted answers (you know, the kind of answer you get from a know-it-all geek), although the answer was there.
 
So here's the beef:
 
System.ComponentModel.DesignerProperties.GetIsInDesignMode(this);
 
This returns a boolean, and "this" is your UserControl or something that is a DependencyObject.

Tuesday, December 8, 2009

Updating WPF window from background thread

I like to do things in the background--you know, you've got a long-running process, so you don't want to bother the user while it runs.

But you want to notify the user when the process is done.  Trouble is, since the background process is running in a different thread from the user interface, the process crashes if you make any attempt to update the user interface directly.

Here's some sample code to solve this with the Dispatcher--kind of well known, but nice to document anyhow:


void UpdateText(string text)
{
    if (this.Dispatcher != System.Windows.Threading.Dispatcher.CurrentDispatcher)
    {
        this.Dispatcher.Invoke(new Action(Update), text);
    }
    else
    {
        this.sampleTextBox.Text = text;
    }

}

Monday, December 7, 2009

C# Inheritance, Typecasting, and Reflection

Did you know that an inherited class cannot be cast into its base class so that reflection will think it's working with the base class?



This proved a minor nuisance as the code had a simplistic work-around, but this might not always be the case.



Below is an example of what I'm talking about:


using System.Reflection;
public static class UtilityClass
{
    public static object GetResult(object workClass)
    {
        string ResultingClassName = "Result" + workClass.GetType().ToString();
        Type provider = Type.GetType(ClassName, true);
        ConstructorInfo constructor = provider.GetConstructor(new Type[0]);
        return constructor.Invoke(new object[0]);
    }
}


public class ResultClass
{
    public ResultClass()
    {
    }
}
public class Class
{
    public ResultClass GetResult()
    {
        return (ResultClass)UtilityClass.GetResult(this);
    }
}
public class ChildClass : Class
{
    public void DoTest()
    {
        ResultClass x = ((Class)this).GetResult();
    }
}

The above code will fail with an exception when DoTest() in ChildClass is called, because it will try to create ResultChildClass, which does not exist.  No matter how you cast, you can't get this to work, because the GetResult method of UtilityClass, using Reflection, will always identify the object for what it really is.

In my case, the solution was to simply create a new "Class" object and copy the base of the ChildClass object into it, then call the "GetResult" method to get my "ResultClass".

Friday, December 4, 2009

System.OutOfMemoryException from Visual Studio

Lately, with my WPF project, I commonly get OutOfMemoryException whey I try to run my project. Visual Studio builds the project, then gets the exception when it tries to start up the executable.

I found a decent work-around is to Build the solution first. Then run the solution. This two-step process seems to solve the issue in that when you run it, Visual Studio doesn't build it--so I guess it's got time to clean up memory before starting your executable.

You might eventually still run out of memory, but this'll give you some extra time before you have to close Visual Studio and start it up again.

Thursday, December 3, 2009

XAML Binding to Datasets

Found that DataSets make lousy binds for WPF forms when the data must be updated from something other than directly by the user, because datasets do not implement INotifyPropertyChanged.

Datasets are great when the data is OneWay binding, because heirarchical data relationships are so easy to define. But you've got to get creative and use something else, such as a BindingList<> when the binding must be TwoWay or OneWayToSource.

Wednesday, December 2, 2009

XAML and the loss of Intellisense

Last week I reported losing my intellisense and tag completion on XAML pages.
 
I finally figured out the cause--and it's not good.  I happend to start up a new solution with a single page and all of a sudden I noticed I had my Intellisense and tag completion back!
 
After getting all excited about it, I went back to my original solution that was having problems--Intellisense and code completion disappeared.
 
Yet they came back with the nothing of a solution.
 
Okay--I get the hint.  XAML and WPF take lots and lots of RAM.  I have only 2GB.  From what I'm gathering, you need at least 3GB RAM.
 
All this only after I totally hosed up my Visual Studio trying to figure it all out.
 

Tuesday, December 1, 2009

Using Syncfusion

I'll give the support team at Syncfusion credit--they do seem to respond quickly to help you out.
 
But I'd give the development team there a failing grade.  They seem to be prone to deploy rather buggy controls for WPF use.
 
Seems getting "NullReferenceException" is commonplace with their controls.  And I just stumbled onto a stupid one--using their DateTimeEdit control and setting the MinDateTime attribute causes the control to display "01/01/0001" as its datetime value.  These kind of bugs are extremely annoying when you are trying to get a job done.  They're so bad that I don't know how they get away with charging for them when so many open-source and non-buggy alternatives are available.  Had I been give the ability to choose which controls to use, Syncfusion would never have been considered.
 
Fortunately, I stumbled onto http://wpf.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=29117.  There is a DatePicker control there that'll work for me--and there's probably a large number of other controls.  Especially since Syncfusion is about as crappy as it comes--try finding what you need without asking their support department--I'm going to trash the Syncfusion control usage wherever possible.