Posts Tagged ‘Code Example’

C# .Net – How to capture a close button press on a Office Custom Task pane

April 27, 2011

When developing our office custom task pane we wanted to control whether pane was displayed when the office application started.

Initially we implemented a ribbon menu that toggled the panes visibility. When the user toggled the pane, we stored the visibility in the registry so that the next time the office application started we would only show the pane if it was required.

But, if the user closed the pane via its close button rather than the toggle button then we would not update the registry.

The solution was to update the registry when the pane visibility changed rather than when the toggle method is called.

There are a couple of events exposed on _CustomTaskPaneEvents_Event interface:

  1. DockPositionStateChange
  2. VisibleStateChange

The VisibleStateChange event is fired when ever the pane shows or is removed.

public void CTPFactoryAvailable( ICTPFactory CTPFactoryInst ) {
    CTP = CTPFactoryInst.CreateCTP(
        typeof( OfficeTaskPanelControl ).FullName,
        "Perfion", Type.Missing );

CTP.VisibleStateChange += CTP_VisibleStateChange;

    CTP.Visible = true;
    CTP.Width = 250;
}

void CTP_VisibleStateChange( CustomTaskPane CustomTaskPaneInst ) {
    // Update the registry at this point. RegHlp.Set("PanelVisibility", "" + CTP.Visible );
}
Advertisements

C# .Net – Render XAML to Image

April 26, 2010

I’ve been trying to find a way to render XAML to PDF or SVG but I’ve had no luck in finding code examples on how to do this. So, for the moment I’ve resorted to rendering XAML to an Image.

Here are the code snippets that I came up with do the job. This code requires .Net Framework 3.5 or later.

Please leave comments if you know how to get from XAML to PDF via an API. I would be really grateful.

public static Stream XamlToImageSteam(
    XmlTextReader xmlReader, BitmapEncoder encoder, Stream outputStream,
    double dpiX, double dpiY ) {

    Window wind = new Window();
    wind.WindowStyle = WindowStyle.None;
    wind.ShowInTaskbar = false;
    wind.ShowActivated = false;

    // Create Minimized so the window does not show. wind.WindowState = System.Windows.WindowState.Minimized;
    wind.SizeToContent = SizeToContent.WidthAndHeight;

    wind.Content = (UIElement)XamlReader.Load(xmlReader);
    wind.Show(); // The window needs to be created for the XAML elements to be rendered. BitmapSource bitmapSrc = visualToBitmap(wind, dpiX, dpiY);

    encoder.Frames.Clear();
    encoder.Frames.Add(BitmapFrame.Create(bitmapSrc));
    encoder.Save(outputStream);

    outputStream.Flush();

    wind.Hide();
    return outputStream;
}
static BitmapSource visualToBitmap( Visual target, double dpiX, double dpiY ) {
    if (target == null) return null;

    Rect bounds = VisualTreeHelper.GetDescendantBounds(target);

    int width = (int)(bounds.Width * dpiX / 96.0);
    int height = (int)(bounds.Height * dpiX / 96.0);

    RenderTargetBitmap renderer = new RenderTargetBitmap(
            width, height, dpiX,
            dpiY, PixelFormats.Pbgra32);

    renderer.Render(target);

    return renderer;
}

Here is an example of rendering some XAML to a png image:-

double dpiX = 96.0;
double dpiY = 96.0;

string xaml =
    "<Page\r\n" +
    " xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n" +
    " xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\r\n" +
    " <Canvas>\r\n" +
    " <Rectangle Width=\"220\" Height=\"100\"\r\n" +
    " RadiusX=\"10\" RadiusY=\"10\" Fill=\"#90d0ff\"/>\r\n" +
    " <TextBlock Canvas.Left=\"25\" Canvas.Top=\"25\"\r\n" +
    " FontSize=\"16\" Foreground=\"White\">Mike Coxeter's .Net Blog</TextBlock>\r\n" +
    " <TextBlock Opacity=\".5\" Canvas.Left=\"26\" Canvas.Top=\"50\"\r\n" +
    " FontSize=\"16\" Foreground=\"White\" >C#, .Net, WPF</TextBlock>\r\n" +
    " </Canvas>\r\n" +
    "</Page>";

XmlTextReader xmlReader = new XmlTextReader(new StringReader(xaml));
using (Stream imageStream = File.Create(@"c:\dotNetBlog.png")) {
    XamlToImageSteam(xmlReader, new PngBitmapEncoder(), imageStream, dpiX, dpiY);
}

dotNetBlog Image produced from above Example

Lists that notify when items are added & removed

April 11, 2010

I often find myself wishing that collections such as List<T> could issue notifications when changes are made to the collection.

This could be particularly useful when you expose a collection as a property from a class. It is often desirable to perform some action on the class if the client changes the collection.

Averager averager = new Averager();
IList<double> numbers = averager.Numbers;

numbers.Add(10);
numbers.Add(5);

Assert.IsTrue(averager.Average == 7.5);

numbers.Add(32);

Assert.IsTrue(averager.Average == 15.666666666666666);

In the code above you can see that Averager passes out a standard list. We can modify the list externally and yet the averager object is kept up to date.

public class Averager {
    public Averager() {
        numbers = new ListNotifyChanged<double>();
        numbers.Changed += numbers_Changed;
    }

    public double Average { get; private set; }

    ListNotifyChanged<double> numbers = null;
    public IList<double> Numbers { get { return numbers; } }

    void numbers_Changed( object sender, ListNotifyChanged<double>.ChangedEventArgs e ) {
        Average = numbers.Average();
    }
}

The ListNofityChanged<T> class is a collection class that closely resembles the List<T> class. However, it fires change notifications events when items are added or removed from the list.

Here is the full implementation of ListNofityChanged<T>

/// <summary>
/// A generic list that will notify when there are
/// changes made to the list.
/// </summary>
public class ListNotifyChanged<T> : IList<T> {
    IList<T> list = new List<T>();

    public ListNotifyChanged() { }

    public ListNotifyChanged( int capacity ) {
        list = new List<T>(capacity);
    }

    public ListNotifyChanged( IList<T> list ) {
        this.list = list;
    }

    public ListNotifyChanged( IEnumerable<T> collection ) {
        list = new List<T>(collection);
    }

    public event EventHandler<ListChangedEventArgs> Changed;
    public event EventHandler<EventArgs> Cleared;

    protected virtual void OnChanged( ListChangedEventArgs e ) {
        if (Changed != null) Changed(this, e);
    }

    protected virtual void OnCleared() {
        if (Cleared != null) Cleared(this, new EventArgs());
    }

    #region IList<T> Members

    public T this[int index] {
        get { return list[index]; }
        set {
            list[index] = value;
            OnChanged(new ListChangedEventArgs(index, value));
        }
    }

    public int IndexOf( T item ) {
        return list.IndexOf(item);
    }

    public void Insert( int index, T item ) {
        list.Insert(index, item);
        OnChanged(new ListChangedEventArgs(index, item));
    }

    public void RemoveAt( int index ) {
        T item = list[index];
        list.Remove(item);
        OnChanged(new ListChangedEventArgs(index, item));
    }

    #endregion

    #region ICollection<T> Members
    public void Add( T item ) {
        list.Add(item);
        OnChanged(new ListChangedEventArgs(list.IndexOf(item), item));
    }

    public void Clear() {
        list.Clear();
        OnCleared();
    }

    public bool Contains( T item ) {
        return list.Contains(item);
    }

    public void CopyTo( T[] array, int arrayIndex ) {
        list.CopyTo(array, arrayIndex);
    }

    public int Count {
        get { return list.Count; }
    }

    public bool IsReadOnly {
        get { return list.IsReadOnly; }
    }

    public bool Remove( T item ) {
        int index = list.IndexOf(item);
        if (list.Remove(item)) {
            OnChanged(new ListChangedEventArgs(index, item));
            return true;
        }
        else
            return false;
    }
    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator() {
        return list.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator() {
        return ((IEnumerable)list).GetEnumerator();
    }

    #endregion

    public class ListChangedEventArgs : EventArgs {
        public int index;
        public T item;
        public ListChangedEventArgs( int index, T item ) {
            this.index = index;
            this.item = item;
        }
    }
}

C# .Net – Writing multiple namespaces with XmlWriter

March 23, 2010

I ran into an error yesterday when writing name spaces using XmlWriter.

I started out trying to write the namespace attributes using WriteAttributeString.

writer.WriteStartElement( "Page" );
writer.WriteAttributeString(
    "xmlns",
    "http://schemas.microsoft.com/winfx/2006/xaml/presentation" );
writer.WriteAttributeString(
    "xmlns:x",
    "http://schemas.microsoft.com/winfx/2006/xaml/presentation" );

When run, XmlWriter threw an exception :-

The prefix ” cannot be redefined from ” to ‘http://schemas.microsoft.com/winfx/2006/xaml/presentation’ within the same start element tag.

After a digging around I found the solution was output the namespaces in the following way:-

writer.WriteStartElement(
    "Page",
    "http://schemas.microsoft.com/winfx/2006/xaml/presentation" );
writer.WriteAttributeString(
    "xmlns",
    "x",
    null,
    @"http://schemas.microsoft.com/winfx/2006/xaml" );

 

C# .Net – Using INotifyPropertyChanged with databound classes

March 23, 2010

In the previous blog DataBinding using BindingList<> we bound a list of Contact class objects to a data grid.

One problem with that implementation was if a property on the bound object was updated via logic, rather than via the user interface, then the grid would fail to “Notice” the change.

public class Contact {
    public int ID { get; set; }
    public string Name { get; set; }
}

[TestMethod]
public void ContactChangedFromCode() {

    BindingList<Contact> contacts = new BindingList<Contact>() {
        new Contact() { ID = 1, Name = "Mike" },
        new Contact() { ID = 2, Name = "Joe" }};

    Form frm = new Form();
    DataGrid grid = new DataGrid() { Dock = DockStyle.Fill, DataSource = contacts };
    frm.Controls.Add(grid);
    frm.Show();

    // Wait for a second for (int i = 1; i < 1000; i++) {
        System.Windows.Forms.Application.DoEvents();
        System.Threading.Thread.Sleep(1); // Sleep for a bit }

    // Updating an entry from Code. contacts[0].Name = "Mike Coxeter";

    // Wait for 5 seconds for (int i = 1; i < 5000; i++) {
        System.Windows.Forms.Application.DoEvents();
        System.Threading.Thread.Sleep(1); // Sleep for a bit }

}
This example shows a grid which does NOT reflect the change of name from Code.

By implementing the INotifyPropertyChanged interface on the Contact class then the grid will respond to changes to properties.

public class Contact : INotifyPropertyChanged {
    int id = 0;
    public int ID {
        get { return id; }
        set {
            id = value;
            onPropertyChanged("ID");
        }
    }
    string name = string.Empty;
    public string Name {
        get { return name; }
        set {
            name = value;
            onPropertyChanged("Name");
        }
    }

    void onPropertyChanged( string propertyName ) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #region INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion }

Now if ContactChangedFromCode() is re-run then the grid will update as expected.

C# .Net – DataBinding using BindingList

March 20, 2010

The coding example used here are from .NetFramwork 4.0.

Overview

In this blog I would like demonstrate how easy it is to use System.ComponentModel.BindingList class to data-bind strongly typed classes to UI controls.

Traditional data-binding using DataTable

[TestMethod]
public void DataBindingWithDataTable() {
    DataTable contacts = new DataTable();

    contacts.Columns.Add("ID", typeof(int));
    contacts.Columns.Add("Name");
    contacts.Rows.Add(new object[] { 1, "Mike" });
    contacts.Rows.Add(new object[] { 2, "Joe" });

    Form frm = new Form();
    DataGrid grid = new DataGrid() { Dock = DockStyle.Fill, DataSource = contacts };
    frm.Controls.Add(grid);
    frm.ShowDialog();
}

Data-binding using BindingList<>

public class Contact {
    public int ID { get; set; }
    public string Name { get; set; }
}

[TestMethod]
public void DataBindingUsignBindingList() {
    BindingList<Contact> contacts = new BindingList<Contact>() {
        new Contact() { ID = 1, Name = "Mike" },
        new Contact() { ID = 2, Name = "Joe" }};

    Form frm = new Form();
    DataGrid grid = new DataGrid() { Dock = DockStyle.Fill, DataSource = contacts };
    frm.Controls.Add(grid);
    frm.ShowDialog();
}