Naughton Futilities

No Relation

  • Silverlight Business Application - Side Navigation Bar

    If you're using the Silverlight Business Application template, you may have also noticed the recently-released Silverlight 4 Theme Refresh:

    http://www.microsoft.com/downloads/details.aspx?FamilyID=e9da0eb8-f31b-4490-85b8-92c2f807df9e&displaylang=en

    As an experiment, I wanted to move the Navigation links to the left-hand-side of the display, to allow more flexibility to add links at a later stage. (I also added a GridSplitter)

    I've attached the Win7 Solution template, as a proof-of-concept.

    Read more...

  • Silverlight Business Application Themes - ErrorWindow Issues

    If you're using the Silverlight Business Application template, you may have noticed some issues, particularly if you have tried the recently-released Silverlight 4 Theme Refresh:

    http://www.microsoft.com/downloads/details.aspx?FamilyID=e9da0eb8-f31b-4490-85b8-92c2f807df9e&displaylang=en

    The text in the OK button is cropped in the new Themes. This is because the Button is defined with fixed Height and Width. Changing these attributes to MinHeight and MinWidth deals with that problem.

    <Button

    x:Name="OKButton"

    Grid.Row="3"

    Click="OKButton_Click"

    MinWidth="75"

    MinHeight="23"

    HorizontalAlignment="Right"

    Margin="0,10,0,0"

    TabIndex="0"

    Content="{Binding Path=ApplicationStrings.OKButton, Source={StaticResource ResourceWrapper}}" />

    Also, the Binding to text Resources does not work as expected. This is because the ErrorWindow expects the ResourceWrapper class to expose an ErrorResources property, which it doesn't. This is another simple fix.

    public sealed class ResourceWrapper

    {

    private static ApplicationStrings applicationStrings = new ApplicationStrings();

    private static SecurityQuestions securityQuestions = new SecurityQuestions();

    private static ErrorResources errorResources = new ErrorResources();

    /// <summary>

    /// Gets the <see cref="ApplicationStrings"/>.

    /// </summary>

    public ApplicationStrings ApplicationStrings

    {

    get { return applicationStrings; }

    }

    /// <summary>

    /// Gets the <see cref="SecurityQuestions"/>.

    /// </summary>

    public SecurityQuestions SecurityQuestions

    {

    get { return securityQuestions; }

    }

    /// <summary>

    /// Gets the <see cref="ErrorResources"/>.

    /// </summary>

    public ErrorResources ErrorResources

    {

    get { return errorResources; }

    }

    }

    I tweaked the 3 new Themes, then repackaged them in the original ZIP format. Simply UnZIP the attached file and follow the original instructions to deploy them to Visual Studio 2010.

    (Note: I also changed App.xaml.cs to always show the ErrorWindow if an UnhandledException occurs).

    Read more...

  • Silverlight 3 DataForm ValueConverter - Add Extensibility

    A recent post described how to obtain extensibility, with respect to DataForm Control Mapping:

    http://weblogs.asp.net/naughton/archive/2009/08/01/silverlight-3-dataform-control-mapping-add-extensibility.aspx

    It is also convenient to make the DataFormValueConverter feature extensible.

    The DataFormValueConverter class is used by the DataField as the default binding.Converter setting.

    If we want to have more control over the IValueConverter implementation that gets used by default, we can add a property to DataForm:

    public IValueConverter DataFormValueConverter { get; set; }

    Then, we need to adjust the DataField.UpdateBindingsOnElement method:

    Old:

    if (binding.Converter == null)

    {

    binding.Converter =
    new DataFormValueConverter();

    }

    New:

    if (binding.Converter == null)

    {

    //binding.Converter = new DataFormValueConverter();

    IValueConverter dataFormValueConverter = null;

    DataForm parentDataForm = this.GetParentDataForm();

    if (null != parentDataForm)

    {

    dataFormValueConverter = parentDataForm.DataFormValueConverter;

    if (null == dataFormValueConverter)

    {

    dataFormValueConverter =
    new DataFormValueConverter();

    }

    }

    else

    {

    dataFormValueConverter =
    new DataFormValueConverter();

    }

    binding.Converter = dataFormValueConverter;

    }

    Now, in a derived DataForm, I can supply my preferred IValueConverter. For example, I want my IValueConverter to map an empty TextBox.Text to null on the underlying string property:

    The difference between DataFormValueConverter and my class (DataFormExtendedValueConverter) is in bold below:

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

    {

    if (targetType != null && (IsNullableType(targetType) || targetType == typeof(string)))

    {

    String strValue = value as String;if (strValue != null && strValue.Length == 0)

    {

    return null;

    }

    }

    return value;

    }

     

    Read more...

  • Silverlight 3 DataForm Control Mapping - Add Extensibility

    An earlier posting explains how to perform basic modifications to the Silverlight 3 DataForm control.

    http://weblogs.asp.net/naughton/archive/2009/08/01/silverlight-3-dataform-control-mapping-basic-modifications.aspx

    It's convenient if such features are available for extensibility.

    This can be achieved in a straightforward fashion too. (A modified DataForm project is attached.)

    The DataForm implements the GenerateField method, which calls the two methods that affect Control mapping.
    Control control = GetControlFromType(propertyType);

    DependencyProperty dependencyProperty = GetBindingPropertyFromType(propertyType);

    We can refactor this area, by introducing a Control Mapping interface (IControlMapper) and a default implementation (ControlMapper).

    Note: I wanted access to the Custom Attributes on each Property, since Custom Attributes may contain information that influences the Control Mapping process. As such, I tweaked the GenerateField method signature to accept the PropertyInfo for the current Property.

    We add a property to DataForm:

    public IControlMapper ControlMapper { get; set; }

    The GenerateField calling code then changes to the following:

    private bool GenerateField(PropertyInfo propertyInfo, Type propertyType, string propertyName, BindingMode bindingMode, Panel panel)

    ...

    IControlMapper controlMapper = this.ControlMapper;
    if (null == controlMapper)

    {

    controlMapper = new ControlMapper();

    }

    controlMapper.PropertyInfo = propertyInfo;

    controlMapper.PropertyType = propertyType;

    Control control = controlMapper.GetControl();

    DependencyProperty dependencyProperty = controlMapper.GetBindingProperty();

    ...

    We can now define a derived DataForm class that supplies a different implementation of IControlMapper that performs the required mapping.

    public interface IControlMapper

    {

    PropertyInfo PropertyInfo { get; set; }

    Type PropertyType { get; set; }

    Control GetControl(); DependencyProperty GetBindingProperty();

    }

    Here is the refactored ControlMapper base class:

    public class ControlMapper : IControlMapper

    {

    #region IControlMapper Members

    protected PropertyInfo propertyInfo;

    public PropertyInfo PropertyInfo

    {

    get

    {

    return this.propertyInfo;

    }

    set

    {

    this.propertyInfo = value;

    }

    }

    protected Type propertyType;public Type PropertyType

    {

    get

    {

    return this.propertyType;

    }

    set

    {

    this.propertyType = value;

    }

    }

    public virtual Control GetControl()

    {

    Type type = this.PropertyType;

    Debug.Assert(type != null, "The type must not be null.");

    if (type == typeof(bool))

    {

    return new CheckBox();

    }

    else if (type == typeof(bool?))

    {

    CheckBox checkBox = new CheckBox();

    checkBox.IsThreeState = true;

    return checkBox;

    }

    else if (type == typeof(DateTime) || type == typeof(DateTime?))

    {

    return new DatePicker();

    }

    else if (type.IsEnum)

    {

    ComboBox comboBox = new ComboBox();

    FieldInfo[] valueFieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static);

    List<string> valueList = new List<string>();foreach (FieldInfo valueFieldInfo in valueFieldInfos)

    {

    Enum value = valueFieldInfo.GetValue(null) as Enum;

    if (value != null)

    {

    valueList.Add(value.ToString());

    }

    }

    comboBox.ItemsSource = valueList;

    return comboBox;

    }

    else

    {

    return new TextBox();

    }

    }

    public virtual DependencyProperty GetBindingProperty()

    {

    Type type = this.PropertyType;

    Debug.Assert(type != null, "The type must not be null.");

    if (type == typeof(bool) || type == typeof(bool?))

    {

    return CheckBox.IsCheckedProperty;

    }

    else if (type == typeof(DateTime) || type == typeof(DateTime?))

    {

    return DatePicker.SelectedDateProperty;

    }

    else if (type.IsEnum)

    {

    return ComboBox.SelectedItemProperty;

    }

    else

    {

    return TextBox.TextProperty;

    }

    }

    #endregion

    }

     

    Read more...

  • Silverlight 3 DataForm Control Mapping - Basic Modifications

    The new DataForm control in the Silverlight Toolkit July 2009 Release does a very nice job of presenting an object in a Form view.

    If you want to take more control of the default way in which the object's properties are mapped to controls, you can open up the DataForm source code and alter the behaviour.

    By default, the source code is zipped up at this location upon installation:

    C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Jul09\Source\Source code.zip

    The DataForm project can be viewed by loading the RiaClient.Toolkit.sln solution file.

    The methods to modify are these (in System.Windows.Controls.Data.DataForm.Toolkit/DataForm/DataForm.cs):

    GetControlFromType

    GetBindingPropertyFromType

    If you modify the GetControlFromType method, you may need to alter GetBindingPropertyFromType to synchronise the processing.

    Their original definition is as follows:

    private static Control GetControlFromType(Type type)

    {

    Debug.Assert(type != null, "The type must not be null.");if (type == typeof(bool))

    {

    return new CheckBox();

    }

    else if (type == typeof(bool?))

    {

    CheckBox checkBox = new CheckBox();

    checkBox.IsThreeState = true;return checkBox;

    }

    else if (type == typeof(DateTime) || type == typeof(DateTime?))

    {

    return new DatePicker();

    }

    else if (type.IsEnum)

    {

    ComboBox comboBox = new ComboBox();

    FieldInfo[] valueFieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static);

    List<string> valueList = new List<string>();

    foreach (FieldInfo valueFieldInfo in valueFieldInfos)

    {

    Enum value = valueFieldInfo.GetValue(null) as Enum;if (value != null)

    {

    valueList.Add(value.ToString());

    }

    }

    comboBox.ItemsSource = valueList;

    return comboBox;

    }

    else

    {

    return new TextBox();

    }

    }

     

    private static DependencyProperty GetBindingPropertyFromType(Type type)

    {

    Debug.Assert(type != null, "The type must not be null.");if (type == typeof(bool) || type == typeof(bool?))

    {

    return CheckBox.IsCheckedProperty;

    }

    else if (type == typeof(DateTime) || type == typeof(DateTime?))

    {

    return DatePicker.SelectedDateProperty;

    }

    else if (type.IsEnum)

    {

    return ComboBox.SelectedItemProperty;

    }

    else

    {

    return TextBox.TextProperty;

    }

    }

    Read more...

  • Detect Installed Version of WSE

    I asked this question a few months ago but there have been two service packs
    since then.

    Can anyone recommend a reliable mechanism for the detection of WSE1/WSE2
    being installed on a PC?

    For example, are there certain installed files and/or registry settings that
    exclusively indicate WSE2?

    Read more...