Archive

Posts Tagged ‘Controls’

WPF NotifyIcon 1.0.5 Released

November 25th, 2013

I just published a maintenance release of my NotifyIcon control, which addresses a few (long due) issues, most notably for applications that target more recent versions of the .NET framework, or x64 applications.

Source code and samples can be downloaded via the control’s project page. Alternatively, there’s now also an official NuGet package for the control (binaries only) that contains builds for .NET 3.5 up to 4.5.1.

What’s next?

I already started working on a new version of the control. The most important feature will be interactive tooltips (so you can hover over them and interact with clickable content), along with a few minor new features. Check back in a few days/weeks, or follow me on Twitter in order to get the update once it’s released. Also, if you have specific feature requests, let me know!

 

WPF TreeView Update

April 7th, 2008

I’ve posted an update for my WPF TreeView which contains a bugfix and two new features:

  • The root item collection is now monitored for changes, and the tree updates itself automatically. This behaviour, however, can be controlled through the ObserveRootItems dependency property.
  • Built-in filtering support through a strongly typed predicate. I’m not completely happy with my implementation though – as a matter of fact, I’ve already started to rewrite it completely – you can expect the next version within the next 10 days. The filtering API however, will remain intact.

In case you did override some of the tree’s virtual methods, your project might not compile out of the box because some of these methods now receive additional parameters. However, as nothing has been removed, adjusting your code should be a matter of seconds.

I’ve added the download link to the original post:
http://www.hardcodet.net/2008/01/wpf-treeview

Happy coding 🙂

Author: Categories: Open Source, WPF TreeView Tags: , ,

A WPF File Selection control

March 14th, 2008

 fileselector

This is a pretty simple user control, which allows you to display a file dialog to open or save files. Its look can be easily adjusted, and it provides built-in truncation of the file string to a predefined length if necessary. Here’s the XAML for the above sample control:

<files:FileSelector x:Name="openFileSelector"
                    Mode="Open"
                    MaxDisplayLength="50"
                    Height="24"
                    Width="400" />

 

The TextBlock in the screenshot which displays the full file path was simply bound to the control’s FileName dependency property:

<TextBlock Text="{Binding ElementName=openFileSelector, Path=FileName}" />

 

The control does not provide too many extension or styling points – the idea is that you just copy it into your solution, adjust the styling of the control’s contents (Border, Button etc.) and be on your way. The source comes with a small sample project – enjoy 🙂

Download Control

Author: Categories: WPF Controls Tags: ,

A versatile WPF TreeView control

January 24th, 2008

A tutorial is now available on Code Project, so check the article for a detailed overview. And please leave your rating if you like the control 🙂
http://www.codeproject.com/KB/WPF/versatile_treeview.aspx

Update: The latest version is currently only available through the download link below. I’ll update the CodeProject article once the current filtering mechanism has been rewritten:

Download: wpf-treeview.zip (Current version: 1.0.7, updated 2008.04.06)

TreeView example This is a little something I’ve been working on for a while: A replacement (or better: enhancement) of WPF’s built-in TreeView control.

I became aware of the default control’s limitations during my last project – I naturally started with hierarchical data templates, but was soon confronted with quite a few issues: I missed a simple API to control the tree, and styling of the tree’s nodes proved hard as well. Furthermore, WPF’s TreeView tends to fire all sorts of SelectedItemChanged events if it’s being refreshed or rebound, which caused side-effects with TwoWay data binding.

However, instead of posting a rant that probably nobody would ever read (let alone care about), I worked on an alternative. Here’s the tree’s main features at a glance:

  • Simple declaration:
    <local:ProductTree x:Name="MyTree"
                       Items="{Binding Source={StaticResource Shop},
                              Path=Products}"
                       SelectedItem="{Binding ElementName=MyProductList,
                              Path=ActiveItem, Mode=TwoWay}"
                       NodeContextMenu="{StaticResource CategoryMenu}"
                       TreeNodeStyle="{StaticResource SimpleFolders}"
                       TreeStyle="{StaticResource SimpleTreeStyle}"
                       SelectedItemChanged="OnSelectedItemChanged"
    />
  • Simple and type safe API:
    //bind flat list of business objects to tree
    List<Product> products = GetProducts();
    myTree.Items = products;
    
    //select a given item
    Product foo = GetBestSellingProduct();
    myTree.SelectedItem = foo; 
    
    //SelectedItem is of type Product - no casts required
    Product bar = myTree.SelectedItem;
  • Lazy loading support – does not create tree nodes until the parent node is expanded. Also provides the option to automatically clear invisible tree nodes. This allows either virtualized trees in case getting data is expensive, or low memory trees that keep the number of tree nodes at a minimum.
  • Simple sorting.
  • Convenient context menu handling for tree nodes
  • Optional root node which is not dependent on the tree’s bound items
  • Simple styling on every level: Tree, TreeViewItem, or bound items (via DataTemplates).
  • Tree layout can be cached, saved and reapplied.
  • Access to tree nodes (TreeViewItem) through bound items.
  • AutoCollapse feature / ExpandAll / CollapseAll methods

All this goodness comes at a price: The TreeViewBase class that provides this functionality, is abstract. This means you have to write a little code yourself. However, you’ll probably manage with 3 lines of code, as the base control just needs to know 3 things:

  • How to generate an identifier for a given tree node
  • How to access a bound item’s childs, if there are any
  • How to access a bound item’s parent, if there is one

Here’s the complete implementation of the sample application’s tree control:

//a tree control that handles only ShopCategory objects
public class CategoryTree : TreeViewBase<ShopCategory>
{

  //the sample uses the category's name as the identifier
  public override string GetItemKey(ShopCategory item)
  {
    return item.CategoryName;
  }

  //returns subcategories that should be available through the tree
  public override ICollection<ShopCategory>
                             GetChildItems(ShopCategory parent)
  {
    return parent.SubCategories;
  }

  //get the parent category, or null if it's a root category
  public override ShopCategory GetParentItem(ShopCategory item)
  {
    return item.ParentCategory;
  }

I’m planning to write a CodeProject article for this one, but for now, it’s only available through my place without a tutorial. However: The library comes with a sample project that shows pretty much all features of the control. Project format is currently VS2008 only, but binaries which target .NET 3.0 are included. Enjoy!

Sample Application

Loaded event of a WPF control may be fired repeatedly

January 21st, 2008

In all my Windows Forms applications, I usually start with a common base class for forms and controls that provides a bunch of convenience properties, subscribes to common events, handles proper cleanup etc. I also implement an empty virtual InitControl method which can be overridden by deriving controls to initialize themselves.

As you can see in the Windows Forms snippet below, InitControl is being called right after the control’s Load event has been fired:

/// <summary>
/// Inits the base class and registers event listeners.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{     
  base.OnLoad(e);
  
  if (!DesignMode)
  {
    InitControlInternal();       
    InitControl();
    initControlCompleted = true;
  }
}


/// <summary>
/// An empty template method which is being invoked after the
/// control has been loaded during <see cref="OnLoad"/>.
/// </summary>
/// <remarks>The base class does not invoke this method if
/// the control is in design mode.</remarks>
protected virtual void InitControl()
{
  //this method is supposed to be overridden. Initialization of
  //the base class itself happens in InitControlInternal
}

 

Naturally, I kept this practice in WPF using the Loaded event which is available for all WPF controls. But to my surprise, InitControl method was getting called repeatedly while I expected it to be called just once, which causes some controls to be re-initialized over and over again. The reason in my case was a TabControl that hosted my user controls. As it turned out, TabControl unloads/reloads user controls with every tab switch.

Unfortunately, there seems to be no common solution to this very problem – you will have to decide how to handle Loaded events specifically for your initialization logic. However:

  • Using Loaded may not be problem in a lot of scenarios, but keep in mind that you might run in trouble when depending on it, especially with a reusable control.
  • You can use the Initialized event of a control rather than Loaded. Check the API documentation for a description of the two events.
  • Use a boolean field to track whether your initialization code has alreay been invoked:

    protected override void InitControl()
    {
      if (initControlCalled) return;
    
      initControlCalled = true;
      //init control
      ...
    }

 

I’ve implemented a short sample that demonstrates the issue. Basically, it’s a tab control that hosts a user control on one of its tab items:

<TabControl>
  <TabItem Header="Tab 1">
    <!-- the user control that counts Loaded events -->
    <local:LoadedCounter />
  </TabItem>

  <TabItem Header="Tab 2">
    <TextBlock>Switch back to trigger event in tab 1.</TextBlock>
  </TabItem>
</TabControl>

 

Once you switch back and forth, you can see that Loaded is being invoked with every switch:

TabControl

Download Sample Project (VS2008)

Author: Categories: WPF Tags: ,