WPF Treeview root node

Unfortunately the WPF native treeview or treeview items do not expose a property to determine which item is the root node in the treeview. I needed such a feature and thought to put it on my blog…

What is a treeview?
Well believe it or not a TreeView is just an Items Control nothing more. Yes, an ItemsControl that creates TreeViewItems as it’s Item Containers. The TreeViewItems are also ItemsControl so a recursive data structure is formed and the TreeViewItems generate there own child nodes.

Today I will not go into details of how the treeview and ItemsControl work… For more info on this visit Dr.Wpf Blog. I will discuss more how I implemented the root nodes for the treeview.

So an ItemsControl has a very special method that one can override to do some custom logic, “PrepareContainerForItemOverride“. The following is the signature of the method

protected override void PrepareContainerForItemOverride(
    DependencyObject element, object item)

Basically this method gets called whenever an item (in our case a TreeViewItem) is being created and decorated with a DataTemplate (if set). In this method we can set a property of the TreeViewItem to identify the item as a root node.Ok, lets start. First we need to sub class the Treeview control. Once we did that we need a way how to attach information to the TreeViewItems… HMMM.. what better could do this then Attached Properties. Once we have all this, we need to set the attached property to True for the root nodes and we are done πŸ™‚ …. something like this

public class MyTreeView : TreeView
    {

        public static bool GetIsRootNode(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsRootNodeProperty);
        }

        public static void SetIsRootNode(DependencyObject obj, bool value)
        {
            obj.SetValue(IsRootNodeProperty, value);
        }

        public static readonly DependencyProperty IsRootNodeProperty =
            DependencyProperty.RegisterAttached("IsRootNode", typeof(bool),
            typeof(MyTreeView), new UIPropertyMetadata(false));

        protected override void PrepareContainerForItemOverride(
            DependencyObject element, object item)
        {
            SetIsRootNode(element, true);
            base.PrepareContainerForItemOverride(element, item);
        }
    }

So the most important part is where we set the Attached property IsRootNode to true (Please also note that by default the Attached property is set to false). You would be wondering, But wouldn’t this make all TreeViewItems root nodes???!!??? And the answer is, NO. Because the Treeview only generate root nodes. all other nodes are generated by the TreeViewItems themselves (Remember that the TreeViewItems are ItemsControl as well :)).

Once we have the property IsRootNode set we can restyle the TreeView as we want by using a Control Template. something like this

<ControlTemplate TargetType="TreeViewItem">
    <StackPanel Margin="10,2,0,0">
        <WrapPanel Name="item">
            <ToggleButton Name="expander"
                          IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                              Path=IsExpanded}"
                          Content="+"/>
            <ContentPresenter x:Name="PART_Header"
                  ContentSource="Header" />
        </WrapPanel>
        <Border>
            <ItemsPresenter Name="children" Visibility="Collapsed" />
        </Border>
    </StackPanel>
    <ControlTemplate.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter TargetName="item" Property="Background"
                    Value="LightBlue"/>
        </Trigger>
        <Trigger Property="IsExpanded" Value="True">
            <Setter TargetName="children" Property="Visibility"
                    Value="Visible"/>
        </Trigger>
        <Trigger Property="HasItems" Value="False">
            <Setter TargetName="expander" Property="Visibility"
                    Value="Collapsed"/>
        </Trigger>
        <Trigger Property="local:MyTreeView.IsRootNode" Value="True">
            <Setter TargetName="item" Property="Background" Value="Silver"/>
            <Setter TargetName="item" Property="Height"  Value="50"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

The most important part of this ControlTemplate is the Trigger on the attached property local:MyTreeView.IsRootNode.Here we are making the RootNodes for the treeview look different from all other nodes…

Hope this post helps…. Please contact me if you need any help πŸ™‚

Download the full source code

Advertisements

Input Prompt support in WPF

Intro

If you look at Vista User experience guide, one thing that is a must have is the Input Prompt. I think that this is very important to improve the user experience. Yet unfortunately this is not supported natively by WPF 😦

But don’t worry because AvalonControlsLibrary is at the rescue πŸ™‚

I had noting to do today so I decided to create this functionality and share it with you guys… You would say, aha; here comes Marlon with a new control. But NO. This is not a control as such. What I have created is a class with some attached properties that can be used to have the Prompt Input feature for any control (or better any control that would make sense such a feature). I choose the attached properties approach rather than creating a custom control for the simple reason to support any control that you wish to have an input prompt like the one displayed in the image below.

Input prompt

As you can see in the image above I am using the Input Prompt both for the TextBox and the ComboBox. And yes you can use it with any control that you want…

How to use this…

Well using this feature is quite easy, all you have to do is to set an attached property in your control. Something like this…

<TextBox local:InputPrompt.PromptText="Enter Search" />

[where local is the XAML namespace mapping]

In total there are 8 properties that you can set which are

  1. InputPrompt.PromptText – I guess you already figured this one out πŸ˜€
  2. InputPrompt.PromptColor – This is a brush used as foreground for the Prompt Text (Default: Gray)
  3. InputPrompt.PromptFontFamily – The font family to use for the Prompt Text (Default: Arial)
  4. InputPrompt.PromptFontSize – The font size of the Prompt Text (Default: 12.0)
  5. InputPrompt.PromptFontStretch – The font stretch to use for the Prompt Text (Default: FontStretches.Normal)
  6. InputPrompt.PromptFontStyle – The font style to use for the Prompt Text (Default: FontStyles.Normal)
  7. InputPrompt.PromptFontWeight – The font weight to use for the Prompt Text (Default: FontWeights.Normal)
  8. InputPrompt.PromptBackColor – This is a brush that is used to color the background of the prompt (Default: Transparent)

Please note: You must set the InputPrompt.PromptText in order for this to work all the other properties are optional. Also you must have you control under an AdornerDecorator because the InputPrompt will draw the prompt text in an adorner.

If you use the Input Prompt with a textbox the input prompt will be much more intelligent. What do I mean by this? Basically the Input Prompt handles the Text Changed event of the TextBox and if the user enters no text the prompt re appears. The same happens if the TextBox looses focus and there is no text in it. I did this behaviour for the TextBox because this is the standard behaviour for an Input Prompt for textboxes.

How does this work behind the scenes

Well it’s quite simple. Basically an Adorner is placed on top of the control which sets the Attached properties and draws the InputPrompt.PromptText. Besides drawing the text this also draws a rectangle covering the surface of the control so that as soon as the user click the control(or better mouse down on the control), the adorner disappears and the control gets activated once again.

When the InputPrompt.PromptText is set for a TextBox, the input prompt will register to the LostFocus event and the TextChanged event and make sure to display the Prompt Text if the Text of the TextBox is to empty.

Conclusion

All this will be included in AvalonControlsLibrary v3 but I decided to upload a demo as a stand alone so that you can start using this immediately.

Hope you like this and as usual I am all ears for feedback and suggestions….

Thanks

Download Source Code and Demo App

kick it on DotNetKicks.com

Support for MinDate and MaxDate in DatePicker and TimePicker

I updated the sources for AvalonControlsLibrary v2 so that to support MinDate and MaxDate in the DatePicker.

Also added support for MinTime and MaxTime in TimePicker.

And while I was at it I also refactored the DateTimePicker to support these 2 properties.

The properties are DependencyProperties so you can easily databind to and do what every you like with them….

Great… now i should go to sleep πŸ˜€

Downlaod the new version

AvalonControlsLibrary v2 has been released !

Finally I had some time to release the new version of AvalonControlsLibrary v2.

This release includes

RangeSlider – All properties are now Dependency properties so that you can easily databind with.
RangeSlider – The RangeSelectedChanged event has been refactored into a Routed event.
Range slider – Support for Commands such as MoveBack Move Forward, AllBack and AllForward

DatePicker – Add a DateSelectedChanged routed event – TimePicker – Add a TimeSelectedChanged routed event

DateTimePicker (this will be the DatePicker and TimePicker joined)

DockableContainer (aka Docky- This is a brand new control which supports docking of element and undocking. While elements are un docked you can drag around the element πŸ™‚ Just like Blend Toolbars)

Bug Fixes
Masked TextBox IsReadonly click here for more info
DateTimePicker – setting the date via code before the ControlTemplate being loaded was thowing an exception

Download the new version

Send as much feedback as you can so that I can start working on V3 πŸ˜€

Thanks for all your support

kick it on DotNetKicks.com

GridViewColumn DisplayMemberBinding vs CellTemplate

GridViewColumn has 2 different ways how one can specify the content of a cell. One can use the DisplayMemberBinding or also a CellTemplate. DisplayMemberBinding is used when you just want to show some text inside your GridViewColumn. You can use this property as follows

<ListView>
    <ListView.View>
         <GridView>
             <GridViewColumn DisplayMemberBinding="{Binding Name}"
                                    Header="Name"/>
         </GridView>
    </ListView.View>
</ListView>

So basically all you have to do is specify a binding to the property of the object being bound. In reality the DisplayMemberBinding will create a TextBlock and bind the Text property of the TextBlock to the binding that you specify. Yet if you need more than just text in a TextBlock then DisplayMemberBinding is not what you should be looking for. For such scenario one should use the CellTemplate.

The CellTemplate property of the GridViewColumn allows you to enter a DataTemplate where you can put in whatever you like as controls to be rendered by the GridView. Let me give you an example of how one can use the CellTemplate to do something more than Text

<ListView>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Image">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Image}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

So in the above example the ListView is now rendering an image where the source of the image is set via a binding to a property of the object being bound to. This gives you much more flexibility in terms of what you can do inside a Cell. For even more advanced scenarios where you have to decide how to render the cell according to the object being bound you can also use the CellTemplateSelector.

Final and most important point about these 2 properties…
DO NOT USE THEM TOGETHER!

If you set the DisplayMemberBinding it is useless to set the CellTemplate because the GridView will only use the DisplayMemberBinding and ignore the CellTemplate. So always make sure that you only set one of these properties and not both at the same time otherwise you will not get the results that you were hoping for.

Want to read some more on ListView? Click here

WPF TextBox Memory Leak???

While running around in the WPF forums, I found this very interesting post… It seems that the WPF TextBox can be dangerous πŸ™‚ – if you do not use it carefully πŸ™‚

Basically the TextBox by default stores all text changes in an Undo Stack… This implies that every time that you change the Text of the TextBox more memory is consumed by the TextBox.

In order to fix this you have to set the UndoLimit property to 0. This would disable the Undo feature for the TextBox and thus NO MORE MEMORY CONSUMPTION

Have a nice day

Embed code in XAML

Loads of time I needed a converter that does a very small operation such as binding to the Height of an element and subtract 10 from the binded value. Every time you have to create a converter to do so. I must admit, it really makes me angry because I would like to this in XAML.

I found this cool code sample on Dynamic Expression API from msdn and I thought why don’t I use it to be able to embed code in XAML…. Apparently I am not the first one trying this out . While having a chat with WPF Guru, Josh Smith, he pointed out that someone else created something similar. M. OrΓ§un Topdağı did a very great job in creating converters that can be declared in XAML. Great Job dude!!! It is really unfortunate that I found out about this after I created my own 😦

Anyway now that I did it might as well show it to you guys right πŸ™‚ So basically this is quite simple. I created a Markup Extension called LambdaValueConverter that creates an instance of a converter that accepts a LambdaExpression which is then compiled (using the Dynamic Expression API) and run whenever the binding for the converter changes. In order to use this LambdaValueConverter you have to pass the Lambda Expression that you want to evaluate when the binding changes. Let me give you an example. Imagine you want to bind to the Height property of a Grid and divide it’s height by 2 and subtract 20. You would do something like this in the Binding

Binding Lambdas1

As you can see this is quite easy to use… It is important to note that param is a predefined variable that holds the binding value (in the case of this example it will be a Double since we are binding to the height property of a Grid). In the expression you can write anything that is supported in the Dynamic Expression API.

One handy feature I added, is support for strings. Imagine you want to concatenate a string with a binding value. Instead having to create 2 TextBlocks and loads of other things, all you have to do is to enter the text you want + the param that is supplied to you by the converter. You have to surround your string with the $ symbol(don’t ask why I choose this symbol πŸ˜€ ) in order for the parser to know that the specified text is a string. It would look something like this….

Binding Lambdas2

So as you can imagine the output of this binding will be >> The border size is {the value of the binding}.

Cool…. Yet I wanted to go a step further. Basically I asked myself and said, “where can this fit besides for converters” and BAMM… I said what about having such a feature for the CanExecute of commands.. Usually in the can execute of a command all you do is a one line of code yet you have to create an event handler every time (same problem as converters!) So I created a class that inherits from the CommandBinding class and extended it to support a expression string that can be evaluated as the CanExecute event handler. In order to use this all you have to do is, create an instance of the CommandLambdas class and set the CanExecuteExpression property with a string that is your expression. As context of the expression there are two predefined variables that you can use. param that is the parameter that you are passing for the command and e that is the CanExecuteRoutedEventArgs for the CanExecute event. Lets make an example. Imagine that you have a checkbox that determines if the Command for a button can execute or not. The code for the Button would look something like this

Binding Lambdas3

Just for the sake of the demo I used the Application.New command so that I don’t have to create my own πŸ˜€ Ok, so here we are setting the checkbox as our parameter for the command. Now all we have to do is to declare our command binding. We have to declare a CommandLambdas and set the CanExecuteExpression property. Something like this….

Binding Lambdas4

So what we are doing is to check if the checkbox (that is our command parameter) is checked and if it is, we set the CanExecute. The assignment of the CanExecute is being done for us implicitly by the CommandLambdas class.

Updated: I found this brilliant Library called Blendables… in Blendables there is a very impressive feature called SimpleBinding and Complex Binding (among others) that enable you to write code in the binding in a very clean way… much more nice + powerful than what I did here….

So you can do something like this in the binding

Width={blendables:EvalBinding [{Self}.Height]/2}

That’s nice isn’t it…. Have a look at their Documentation here. Or even check out their samples over here.

Well that is all… I am looking forward for feedback to see how we can extend even more this to be even more useful for WPF Developers πŸ™‚

Looking forward for your feedback.

See also Filterering CollectionViewSource Dynamically

Download Source Code for the AvalonLambdas

kick it on DotNetKicks.com