Monday, July 13, 2009

Why are my WPF MenuItems grayed out

Well not all of them, but only those bound to WPF Commands.

After a 2 hour search, I finally found that a control that had focus, became invisible because it was not necessary anymore. Upon that event, my menuitems became grayed out (IsEnabled became false). Focussing a visible control on the screen resolved my issue.

So it seems that WPF Commands can not be executed when no focussed control is available.

Thursday, May 28, 2009

Databinding and LostFocus (HOWTO Force SourceUpdate for any WPF FrameworkElement)

Today I faced a bug that was not so easy to handle. While editing a value within a WPF textbox I pressed CTRL+S to save my work. Unfortunately my edited data was not saved, but the previous data was instead. How did that happen.

Well my WPF textbox was data bound to my dataobject. The dataobject (source) normally gets updated upon a Lostfocus of the textbox (that’s the default). However pressing CTRL+S (or even selecting the save menuitem under the file menu) does not result in the textbox losing focus.

OK. The short way to handle this problem is to get the binding expression of the textbox on de Text Property. Upon this binding expression it’s possible to call UpdateSource() explicitly and the value gets stored in the bound dataobject.

However I searched for a more generic approach because I do not have textboxes only. And it’s not always the Text Property that is being bound. So searching on the internet, I found a reaction on Nigel Spencer's blog: http://blog.spencen.com/2008/05/02/how-to-get-a-list-of-bindings-in-wpf.aspx#comment-1015806[^].

I modified the code a little bit to fit my needs and here is the result:

using System; 
using System.Windows;
using System.Windows.Data;
namespace MyNamespace
{
internal static class WPFHelper
{
internal static void ActionAllBindings(FrameworkElement targetElement, Action<BindingExpression> action)
{
WalkElementTree(targetElement, action);
}

private static void WalkElementTree(object obj, Action<BindingExpression> action)
{
var dependencyObject
= obj as FrameworkElement;
// Sometimes leaf nodes aren’t DependencyObjects (e.g. strings)
if (dependencyObject == null)
{
return;
}

// Recursive call for each logical child
ActionBindings(dependencyObject, action);
foreach (var child in LogicalTreeHelper.GetChildren(dependencyObject))
{
WalkElementTree(child, action);
}
}

private static void ActionBindings(DependencyObject target, Action<BindingExpression> action)
{
var localValueEnumerator
= target.GetLocalValueEnumerator();
while (localValueEnumerator.MoveNext())
{
var current
= localValueEnumerator.Current;
var binding
= BindingOperations.GetBindingExpression(target, current.Property);
if (binding != null)
{
action(binding);
}
}
}
}
}


Using the helper is extremely simple:



public void ForceSourceUpdateActiveElement()    
{
var focusedElement
= Keyboard.FocusedElement as FrameworkElement;
if (focusedElement != null)
{
MyNamespace.ActionAllBindings(focusedElement, bindingExpression
=> bindingExpression.UpdateSource());
}
}

Friday, January 25, 2008

IList is not serializable in combination with XmlSerializer

Because IList<T> does not implement ICollection (but the generic ICollection<T> instead), the XMLSerializer is not able to serialize the items within the collection. More info on this "bug" can be found here:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105767

Friday, January 4, 2008

Implementing a custom Dispose for a form or usercontrol

Have you ever wanted to implement a custom dispose method for a usercontrol or a form. Trying to override protected void dispose(bool disposing) learns that the designer generated file (mycontrol.designer.cs) already implements this override.

Mark Seemann wrote an intersting approach for dealing with this situation in his blog. It makes use of an Disposer component. A new instance will be created with a reference to a method implementing the custom dispose functionality. This instance is being added to the components collection. When the components get disposed, the this Disposer calls the delegate function with custom dispose logic. That's it.

Thanks Mark for this article.

Wednesday, August 15, 2007

Error: Validation of viewstate MAC failed. in ASP.NET page

Full error:

Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the
same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.


This error may occur when one hosts an ASP.NET webpage on a web-garden.

Simple solution (for ASP.NET 2.0 and up): Generate a new machinekey and add it to the web.config.

Full explanation can be found in the blog of Jody.

Friday, June 8, 2007

Programmatic databinding between classes and controls

It's possible to programmatically databind to controls with the following statement:

myLabel.DataBindings.Add("Text", myObject, "Name");

However there are some specific controls that have trouble using databinding. Some should use another property, like Value or SelectedItem, while others need a specific
DataSourceUpdateMode. From my experience here's a list of controls and possible databindings:

  • Label
    myLabel.DataBindings.Add("Text", myObject, "Name");
  • TextBox
    myLabel.DataBindings.Add("Text", myObject, "Name");
  • NumericUpDown
    myNumericUpDown.DataBindings.Add("Text", myObject, "Age");
  • ComboBox
    mycomboBox.DataBindings.Add("SelectedItem", myObject, "Option", false, DataSourceUpdateMode.OnPropertyChanged);

Wednesday, May 16, 2007

Help not always on top!

Today I was asked whether it was possible to show the help in a non-modal manner. After a little searching on the internet, I found the following solution, posted in a forum by Rodger Constandse. It's a little trick but it works faboulous:

Create a new Form (once for an application). Call CreateControl() on it in order to create a handle to it, but it will not show up. See the following code-example:

public class MyApp
{
// Create a form as the parent for the Help window.
private Form m_HelpFormParent = new Form();

public MyApp()
{
// Enforce creation of a handle to the form
m_HelpFormParent.CreateControl();
}

public ShowHelp(string url, HelpNavigator command, object parameter)
{
// Call ShowHelp with the form created for this purpose as parent
Help.ShowHelp(HelpFormParent, url , command , parameter );
}
}