27 January 2011

.NET - Using the clipboard

I used following code to insert text at cursor position in a textbox from a context menu on a ListBox:

Clipboard.SetData(DataFormats.Text, text);

txtQuery.Paste();

26 January 2011

Silverlight - Child window

In Silverlight, you can create a child window using Add > New Item > Silverlight Child Window. Such window creates a class and doesn't need to be embedded in the XAML from which you want to open it. You open it in code with a simple:

new frmLeadEdit().Show();

The window overlays the entire Silverlight area and blocks underlaying controls. I customized it's style. Make sure the styles TargetType has the proper prefix. I had a browser crash without it.

The window can return a 'DialogResult' of True or False. To receive it, you must handle the windows 'Closed' event.

19 January 2011

XAML - Scaling UI elements with fixed width and height

Sometimes you want the size of a XAML UI element to be dynamic and set it's width and height at the same time. This can be done by:
  • Adding the following using:

    xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"

  • Wrapping the UI element in following tag:

    <toolkit:Viewbox Stretch="Uniform">

    </toolkit:Viewbox>

14 January 2011

.NET - Custom event

Sometimes you need to throw your own custom event with custom arguments. The arguments can be passed directly or by implementing a custom class that inherits from EventArgs. The latter is needed when adding handlers on the event in for instance XAML. The event can be e.g.:

public delegate void ValidationEventHandler(object sender, ValidationEventArgs e);
public event ValidationEventHandler Validation;
protected virtual void OnValidation(string propertyName, bool isValid, string message) {
  if (Validation != null)
    Validation(this, new ValidationEventArgs(propertyName, isValid, message));
}

Which can then be raised by:

OnValidation("Code", false, "Value must not be empty.");

Or you skip the helper method. Make sure the event is not null, meaning there are no listeners:

Validation?.Invoke(this, new ValidationEventArgs(nameof(Code), false, "Value must not be empty."));

You can also use the generic delegate. It can be invoked the same way.

public event EventHandler<ValidationEventArgs> Validation;

.NET - Implementing INotifyPropertyChanged

To implement the INotifyPropertyChanged interface on a business object:
  • Implement the interface System.ComponentModel.INotifyPropertyChanged,
  • Add a method like this:
    private void NotifyPropertyChanged([CallerMemberName]string propertyName = null) =>
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
  • Use this method in every setter that must notify:
    NotifyPropertyChanged();

.NET - Decorate object properties for data binding

If you set the AutoCreateColumns property of a DataGridView to True, all public properties of a bound object type will appear as columns. However, you can manipulate how they appear by decorating these properties.

Using [Browsable(false)], the property will not be added as a column.

Using [DisplayName("The header text")], you set the column header text for the property.

07 January 2011

SharePoint - Install custom web service

To install a custom web service in SharePoint (2007):
  • Create a web service assembly and build it,
  • Set it's 5-part strong name as class attribute in the asmx file (right-click > View Markup),
  • Install the signed assembly in the GAC,
  • Put the asmx in the 12\TEMPLATE\LAYOUTS folder,
  • Copy disco.exe (the tool) to the same location,
  • Run a command prompt and cd to that location,
  • Run the command disco http://<server>/_layouts/<service>.asmx,
  • Include the 2 generated files *.disco and *.wsdl in the web service project,
  • Remove the '.' preceding their extensions and append ".aspx" to their names,
  • In the *disco.aspx file, replace everything by the following. Don't change anything to the headers, not even put them on new lines, as SharePoint won't find the file anymore. The same goes for the WSDL that comes next.
    <%@ Page Language="C#" Inherits="System.Web.UI.Page" %> <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint.Utilities" %> <%@ Import Namespace="Microsoft.SharePoint" %>
    <% Response.ContentType = "text/xml"; %>
    <discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
    <contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + "?wsdl"),Response.Output); %> docRef="http://www.syneton.be/_layouts/SynetonService.asmx" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
    <soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns:q1="http://www.syneton.be/services/" binding="q1:SynetonServiceSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
    <soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns:q2="http://www.syneton.be/services/" binding="q2:SynetonServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
    </discovery>
  • In the *wsdl.aspx file, add the following to the top of the file:
    <%@ Page Language="C#" Inherits="System.Web.UI.Page" %> <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint.Utilities" %> <%@ Import Namespace="Microsoft.SharePoint" %>
    <% Response.ContentType = "text/xml"; %>

    And at the bottom, replace the location attribute of <soap:address... and <soap12:address... both as follows:
    location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
  • Now put those 2 files and the asmx under 12\ISAPI and it's done.
  • The service is now available from http://<server>/_vti_bin/<service>.asmx.

    PHP - Starts|ends with

    Two convient general purpose functions from .NET for PHP:

    function startsWith($Text, $Value){
      return strpos($Text, $Value) === 0;
    }
    
    function endsWith($Text, $Value){
      return strrpos($Text, $Value) === strlen($Text) - strlen($Value);
    }
    

    06 January 2011

    SharePoint - Deploy custom field

    In SharePoint (2007), custom fields — custom column types you can add to lists — are deployed through 3 steps:
    • Install the signed assembly in the GAC,
    • Deploy the fldtypes*.xml to \12\TEMPLATE\XML,
    • Deploy the *.ascx without it's .cs to \12\TEMPLATE\CONTROLTEMPLATES.
    After an IISRESET the thing should then work.

    Notes on custom fields, e.g. for the error Type X not found:
    • Make sure the DefaultTemplateName matches the ID of the RenderingTemplate.

    05 January 2011

    XAML - Custom button style

    An example style for a custom button to put in a resource dictionary:

    Silverlight

    <Style TargetType="Button">
      <Setter Property="Cursor" Value="Hand" />
      <Setter Property="Margin" Value="2" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Grid>
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="Common">
                  <VisualState Name="Normal">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="objBackgroundTop" Storyboard.TargetProperty="Color" Duration="0:0:0.2" From="Green" To="#EEEEEE" />
                    </Storyboard>
                  </VisualState>
                  <VisualState Name="MouseOver">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="objBackgroundTop" Storyboard.TargetProperty="Color" Duration="0:0:0.2" From="#EEEEEE" To="Green" />
                    </Storyboard>
                  </VisualState>
                  <VisualState Name="Pressed">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="objBackgroundTop" Storyboard.TargetProperty="Color" Duration="0:0:0.2" From="Green" To="CornflowerBlue" />
                    </Storyboard>
                  </VisualState>
                  <VisualState Name="Disabled">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="objBackgroundTop" Storyboard.TargetProperty="Color" Duration="0:0:0.2" From="#EEEEEE" To="#444444" />
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <Rectangle RadiusX="5" RadiusY="5">
                <Rectangle.Fill>
                  <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                    <GradientStop Offset="0" Color="#EEEEEE" x:Name="objBackgroundTop" />
                    <GradientStop Offset="1" Color="#111111" />
                  </LinearGradientBrush>
                </Rectangle.Fill>
              </Rectangle>
              <ContentPresenter />
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    WPF

    Another example for WPF. Here I used triggers and resources:

    <Style x:Key="Button" TargetType="Button">

      <Style.Resources>

        <LinearGradientBrush x:Key="lgbNormal" StartPoint="0,0" EndPoint="0,1">

          <GradientStop Offset="0" Color="{x:Static SystemColors.ControlLightLightColor}" />

          <GradientStop Offset="0.5" Color="{x:Static SystemColors.ControlLightColor}" />

          <GradientStop Offset="0.5" Color="{x:Static SystemColors.ControlDarkDarkColor}" />

          <GradientStop Offset="1" Color="{x:Static SystemColors.ControlDarkDarkColor}" />

        </LinearGradientBrush>

        <LinearGradientBrush x:Key="lgbMouseOver" StartPoint="0,0" EndPoint="0,1">

          <GradientStop Offset="0" Color="{x:Static SystemColors.ControlLightLightColor}" />

          <GradientStop Offset="0.5" Color="#083B80" />

          <GradientStop Offset="0.5" Color="{x:Static SystemColors.ControlDarkDarkColor}" />

          <GradientStop Offset="1" Color="{x:Static SystemColors.ControlDarkDarkColor}" />

        </LinearGradientBrush>

      </Style.Resources>

      <Setter Property="Template">

        <Setter.Value>

          <ControlTemplate TargetType="Button">

            <Border x:Name="border" BorderThickness="1" BorderBrush="#3E3E3E" CornerRadius="2">

              <Grid>

                <Rectangle x:Name="rect" RadiusX="2" RadiusY="2" Fill="{StaticResource lgbNormal}" />

                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />

              </Grid>

            </Border>

            <ControlTemplate.Triggers>

              <Trigger Property="IsMouseOver" Value="True">

                <Setter TargetName="rect" Property="Fill" Value="{StaticResource lgbMouseOver}" />

                <Setter TargetName="border" Property="BorderBrush" Value="#083B80" />

              </Trigger>

              <Trigger Property="IsEnabled" Value="False">

                <Setter TargetName="border" Property="Opacity" Value="0.5" />

              </Trigger>

            </ControlTemplate.Triggers>

          </ControlTemplate>

        </Setter.Value>

      </Setter>

    </Style>

    XAML - Convert SVG to XAML and use as a resource on a button

    I wanted to use some nice icons in SVG format in Silverlight.
    Silverlight doesn't support SVG though.
    So I found a tool that can convert them to XAML.
    It's a command line tool that can be used as follows:

    svg2xaml D:\Projects\ArrowUp.svg

    To make it valid I had to tweak the result a bit.
    One thing was to remove the PathGeometry's and put their data directly in the Path's.
    Then I surrounded it with:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                       xmlns:toolkit="clr-namespace:System.Windows.Controls;
                                      assembly=System.Windows.Controls.Toolkit">
      <Style x:Key="ArrowUp" TargetType="Button">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="Button">
              <toolkit:Viewbox Stretch="Uniform">
                <!-- The XAML -->
              </toolkit:Viewbox>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </ResourceDictionary>

    put it's build action to "Content" and included it with:

    <this:frmBase.Resources>
      <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
          <ResourceDictionary Source="Images/ArrowDown.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
    </this:frmBase.Resources>

    Then I used the resource as follows:

    <Button Style="{StaticResource MenuButton}">
      <Button.Content>
        <Button Style="{StaticResource ArrowDown}" Click="Button_Click" />
      </Button.Content>
    </Button>

    where "MenuButton" is another global style resource with a custom template containing a ContentPresenter.

    04 January 2011

    Visual Studio - Copy code as HTML

    Here's an add-in for Visual Studio that allows to copy source code in HTML format.
    However, the add-in is for VS 2008, so here's how to get it working in VS 2010, e.g. open the *.AddIn file and changing the version to "10.0".
    Lastly, when copying code, also select the first line fully to get the indentation right.

    CRM - Get CRM service

    To get an instance of the CRM service to send requests to:

    private CrmService GetCrmService() {
      return new CrmService() {
        Url = "http://crm/MSCrmServices/2007/CrmService.asmx",
        CrmAuthenticationTokenValue = new CrmAuthenticationToken() {
          AuthenticationType = 0,
          OrganizationName = "EGS_NV"
        },
        Credentials = CredentialCache.DefaultNetworkCredentials,
        PreAuthenticate = true
      };
    }

    03 January 2011

    XAML - Horizontal align stretch for item template

    To get the content of the item template in a listbox to stretch along with the listbox itself:
    Source (answer 2)

    <ListBox.ItemContainerStyle>
      <Style TargetType="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
      </Style>
    </ListBox.ItemContainerStyle> 

    Other properties of the listbox items can also be set here:

    <Setter Property="IsEnabled" Value="False" />

    Apparantly, however, you can't use bindings in these setters, while WPF does allow this.

    But there is a workaround involving some coding that resolves the issue.

    LINQ - Left outer join

    Left outer join in LINQ where the right table references the left table:
    Source

    result = from o in orders
             join c in coupons on o.Id equals c.Order.Id into c2
             from c3 in c2.DefaultIfEmpty()
             select new ContactCoupon() {
               Contact = o.Contact,
               Coupon = c3
             };