WPF TabControl with close button and editable header

August 9, 2013 Leave a comment

Untitled

 

Xaml

<Window x:Class=”WpfApplication1.Window2″
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
xmlns:theme=”clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic”
xmlns:dx=”http://schemas.devexpress.com/winfx/2008/xaml/core&#8221;
xmlns:this=”clr-namespace:WpfApplication1″
xmlns:sys=”clr-namespace:System;assembly=mscorlib” Title=”Window1″ Height=”300″ Width=”441″ Background=”DarkKhaki”>
<Window.Resources>
<SolidColorBrush x:Key=”TabItemNormalBorderBrush” Color=”#FFF”/>
<SolidColorBrush x:Key=”TabItemDisabledBorderBrush” Color=”#ABCEF9″/>
<SolidColorBrush x:Key=”SolidBorderBrush” Color=”#888″ />
<SolidColorBrush x:Key=”WindowBackgroundBrush” Color=”#FFF” />
<SolidColorBrush x:Key=”DisabledBackgroundBrush” Color=”#EEE” />
<SolidColorBrush x:Key=”DisabledBorderBrush” Color=”#AAA” />
<SolidColorBrush x:Key=”DisabledForegroundBrush” Color=”#888″ />
<SolidColorBrush x:Key=”WindowBackground” Color=”#ABCEF9″ />
<Storyboard x:Key=”startHeaderEdit”>
<ObjectAnimationUsingKeyFrames Duration=”0″ Storyboard.TargetName=”tabHeaderEdit” Storyboard.TargetProperty=”Visibility”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{x:Static Visibility.Visible}” />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration=”0″ Storyboard.TargetName=”tabHeaderPresenter” Storyboard.TargetProperty=”Visibility”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{x:Static Visibility.Collapsed}” />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key=”endHeaderEdit”>
<ObjectAnimationUsingKeyFrames Duration=”0″ Storyboard.TargetName=”tabHeaderEdit” Storyboard.TargetProperty=”Visibility”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{x:Static Visibility.Collapsed}” />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration=”0″ Storyboard.TargetName=”tabHeaderPresenter” Storyboard.TargetProperty=”Visibility”>
<DiscreteObjectKeyFrame KeyTime=”0″ Value=”{x:Static Visibility.Visible}” />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType=”{x:Type TabItem}”>
<Setter Property=”Template”>
<Setter.Value>
<ControlTemplate TargetType=”{x:Type TabItem}”>
<ContentControl>
<theme:ClassicBorderDecorator Name=”ClassicBorder” SnapsToDevicePixels=”true” BorderThickness=”1″ BorderStyle=”Raised”>
<DockPanel x:Name=”tabDockPanel”>
<Button x:Name=”tabCloseButton” Cursor=”Hand” DockPanel.Dock=”Right” Focusable=”False” FontFamily=”Courier” FontSize=”9″ FontWeight=”Bold” Margin=”5,2,3,2″ Padding=”0″ VerticalContentAlignment=”Bottom” Width=”16″ Height=”16″ Click=”tabCloseButton_Click”>
<Path Stretch=”Fill” StrokeThickness=”0.9″
Stroke=”#FFF” Fill=”#FF969696″
Data=”F1 M 2.28484e-007,1.33331L 1.33333,0L 4.00001,2.66669L 6.66667,6.10352e-005L 8,1.33331L 5.33334,4L 8,6.66669L 6.66667,8L 4,5.33331L 1.33333,8L 1.086e-007,6.66669L 2.66667,4L 2.28484e-007,1.33331 Z “
HorizontalAlignment=”Stretch”
VerticalAlignment=”Stretch”/>
</Button>
<this:TabItemTextBox x:Name=”tabHeaderEdit” DockPanel.Dock=”Left” Text=”{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}” Visibility=”Collapsed”>
<this:TabItemTextBox.Triggers>
<EventTrigger RoutedEvent=”this:TabItemTextBox.EnterKeyPressed”>
<BeginStoryboard Storyboard=”{StaticResource endHeaderEdit}”/>
</EventTrigger>
</this:TabItemTextBox.Triggers>
</this:TabItemTextBox>
<ContentPresenter x:Name=”tabHeaderPresenter” SnapsToDevicePixels=”{TemplateBinding SnapsToDevicePixels}” ContentSource=”Header” Margin=”{TemplateBinding Padding}” RecognizesAccessKey=”true” HorizontalAlignment=”{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}” VerticalAlignment=”{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}” />
</DockPanel>
</theme:ClassicBorderDecorator>
<ContentControl.Triggers>
<EventTrigger RoutedEvent=”Control.MouseDoubleClick”>
<BeginStoryboard Storyboard=”{StaticResource startHeaderEdit}”/>
</EventTrigger>
</ContentControl.Triggers>
</ContentControl>
<ControlTemplate.Triggers>
<Trigger Property=”IsSelected” Value=”true”>
<Setter Property=”Panel.ZIndex” Value=”1″ />
<Setter TargetName=”tabDockPanel” Property=”Background” Value=”{StaticResource TabItemNormalBorderBrush}” />
</Trigger>
<Trigger Property=”IsSelected” Value=”false”>
<Setter TargetName=”tabDockPanel” Property=”Background” Value=”{StaticResource TabItemDisabledBorderBrush}” />
<Setter TargetName=”ClassicBorder” Property=”BorderStyle” Value=”TabBottom” />
</Trigger>
<EventTrigger SourceName=”tabHeaderEdit” RoutedEvent=”UIElement.LostFocus”>
<BeginStoryboard Storyboard=”{StaticResource endHeaderEdit}”/>
</EventTrigger>
<Trigger Property=”TabStripPlacement” Value=”Bottom”>
<Setter TargetName=”ClassicBorder” Property=”BorderStyle” Value=”TabBottom” />
</Trigger>
<Trigger Property=”TabStripPlacement” Value=”Left”>
<Setter TargetName=”ClassicBorder” Property=”BorderStyle” Value=”TabLeft” />
</Trigger>
<Trigger Property=”TabStripPlacement” Value=”Right”>
<Setter TargetName=”ClassicBorder” Property=”BorderStyle” Value=”TabRight” />
</Trigger>
<Trigger Property=”IsEnabled” Value=”false”>
<Setter Value=”{DynamicResource {x:Static SystemColors.GrayTextBrush}}” Property=”Foreground” />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<TabControl Name=”tabControlView” Margin=”4″ BorderThickness=”1″ BorderBrush=”Black” Height=”246″>
<TabControl.Items>
<TabItem Header=”Header 1″ Content=”Content 1″ HorizontalAlignment=”Left” VerticalAlignment=”Top”></TabItem>
<TabItem Header=”Header 2″ Content=”Content 2″ HorizontalAlignment=”Left” VerticalAlignment=”Top”></TabItem>
<TabItem Header=”Header 3″ Content=”Content 3″ HorizontalAlignment=”Left” VerticalAlignment=”Top”></TabItem>
</TabControl.Items>
</TabControl>
</StackPanel>
</Window>

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Reflection;
namespace WpfApplication1
{
///
/// Interaction logic for Window2.xaml
///
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void tabCloseButton_Click(object sender, RoutedEventArgs e)
{
TabItem tab = FindVisualParent(sender as DependencyObject);
if (tab != null)
tabControlView.Items.Remove(tab);
}
public static T FindVisualParent(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
return FindVisualParent(parentObject);
}
}
}
public class TabItemTextBox : TextBox
{
public static readonly RoutedEvent EnterKeyPressedEvent = EventManager.RegisterRoutedEvent(“EnterKeyPressed”, RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TabItemTextBox));
public event RoutedEventHandler EnterKeyPressed
{
add { AddHandler(EnterKeyPressedEvent, value); }
remove { RemoveHandler(EnterKeyPressedEvent, value); }
}
Categories: C#, WPF

WPF ItemsControl with dynamic elements style

January 30, 2011 Leave a comment

This control contains one parent ItemsControl and Item1 and Item2 as child items. Style of Item1 and Item2 are selected dynamically based on the property value at runtime. This is done with the help of MultiBinding and a converter class ListBoxSingleMultiConverter. You can find the full source code here.

    <ItemsControl ItemsSource="{Binding Path=DataSource, ElementName=DynamicListControl, diagnostics:PresentationTraceSources.TraceLevel=High, Converter={StaticResource NoOPConverter}}" >
        <ItemsControl.ItemTemplate >
            <DataTemplate>
                <Border>
                    <Expander Margin="0,5,0,2" BorderBrush="Gray" Background="WhiteSmoke" IsEnabled="{Binding IsEnabled}">
                        <Expander.Header>
                            <TextBlock Text="{Binding Path=Name}" FontWeight="bold" Foreground="DarkBlue">   
                            </TextBlock>
                        </Expander.Header>
                        <StackPanel Orientation="Vertical">
                            <DockPanel HorizontalAlignment="Stretch" Margin="0,0,4,2" >
                                <Label Content="{Binding Name}" FontWeight="bold" HorizontalContentAlignment="Left" />                              
                            </DockPanel>
                            <Border BorderBrush="Silver" BorderThickness="1">
                                <ScrollViewer x:Name="CheckListBoxScroller" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
                                    <ListBox x:Name="ListBoxControl" MaxHeight="130" Background="Transparent" 
                                                                         SelectionMode="{Binding Path=IsMultiSelect, Converter={StaticResource BoolToSelectionModeConverter}}">
                                        <ListBox.ItemsSource>
                                            <Binding Path="KeyValuePairs" />
                                        </ListBox.ItemsSource>
                                        <ListBox.DisplayMemberPath>
                                            Value
                                        </ListBox.DisplayMemberPath>
                                        <ListBox.SelectedValuePath>
                                            Key
                                        </ListBox.SelectedValuePath>
                                        <ListBox.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <VirtualizingStackPanel Background="Transparent" Orientation="Vertical" />
                                            </ItemsPanelTemplate>
                                        </ListBox.ItemsPanel>
                                        <ListBox.ItemContainerStyle>
                                            <MultiBinding Converter="{StaticResource ListBoxSingleMultiConverter}">
                                                <Binding RelativeSource="{RelativeSource Self}"/>
                                                <Binding Path="IsMultiSelect"/>
                                            </MultiBinding>
                                        </ListBox.ItemContainerStyle>
                                        <Control.Template>
                                            <ControlTemplate>
                                                <Border BorderThickness="0" Padding="0" BorderBrush="Transparent" Background="Transparent" Name="Bd" SnapsToDevicePixels="False">
                                                    <!--<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"  />-->
                                                    <ScrollViewer Margin="0" Focusable="false">
                                                        <StackPanel Margin="2" IsItemsHost="True" />
                                                    </ScrollViewer>
                                                </Border>
                                            </ControlTemplate>
                                        </Control.Template>
                                    </ListBox>
                                </ScrollViewer>
                            </Border>
                        </StackPanel>
                    </Expander>
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

Download Full Source Code.

Categories: Uncategorized

How to intercept method calls in .net framework

May 13, 2010 Leave a comment

 

This is the core of how Policy Injection Block works in Enterprise Library. I hope you find it useful.

Copy paste this code and see the magic. Magic is done by __TransaparentProxy which is also used by .net remoting. Read More.

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.IO;

using System.Xml;

using System.Xml.Serialization;

using System.Runtime.Serialization;

using System.Globalization;

using System.Runtime.Serialization.Formatters;

using System.Runtime.Serialization.Formatters.Binary;

using System.Threading;

using System.Windows.Forms;

using System.Runtime.Remoting.Messaging;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Proxies;

namespace Test

{

    public class Program

    {

        static void Main(string[] args)

        {

            EmployeeHelper helper = new EmployeeHelper();

            RealProxy proxy = new InterceptorProxy(typeof(EmployeeHelper), helper);

            EmployeeHelper helperProxy = (EmployeeHelper)proxy.GetTransparentProxy();

            string name = helperProxy.GetEmployeeName(0);

            Console.WriteLine("Employee Name " + name);

            Console.Read();

        }

    }

    public class EmployeeHelper : MarshalByRefObject

    {

        public string GetEmployeeName(int id)

        {

            if (id == 0)

            {

                return "Test";

            }

            return String.Empty;

        }

    }

    public class InterceptorProxy : RealProxy

    {

        MarshalByRefObject target;

        public InterceptorProxy(Type classToProxy, MarshalByRefObject target)

            base(classToProxy)

        {

            this.target = target;

        }

        public override IMessage Invoke(IMessage msg)

        {

            IMethodCallMessage callMsg = msg as IMethodCallMessage;

            if (callMsg != null)

            {

                OnMethodCall(callMsg);

                IMethodReturnMessage retMsg = RemotingServices.ExecuteMessage(target, callMsg);

                OnMethodReturn(retMsg);

                return retMsg;

            }

            else

            {

                throw new NotSupportedException();

            }

        }

        void OnMethodCall(IMethodCallMessage callMsg)

        {

            Console.WriteLine("Method call started");

        }

        void OnMethodReturn(IMethodReturnMessage retMsg)

        {

            Console.WriteLine("Method call ended");

        }

    }

}

 

Categories: Uncategorized

Design principles to follow

May 12, 2010 Leave a comment

 

Here are some design principles which I follow whenever I design an application or a feature. Keeping these principles in mind can help you build an architecture that follows proven principles and promotes scalability and extensibility.  These principles applies to any architecture style like Client/Server, Component Based, Domain Driven, Layered, SOA etc..

This is how I remember these……….

Categories: Uncategorized

Design to avoid type casting in derived classes

April 3, 2010 12 comments
public interface IBasePresenter
{
}
public interface IJobViewPresenter : IBasePresenter
{
}
public interface IActivityViewPresenter : IBasePresenter
{
}

public class BaseView
{
    public IBasePresenter Presenter
    {
        get;
        set;
    }
}

public class JobView : BaseView
{
    public IJobViewPresenter JobViewPresenter
    {
        get { this.Presenter as IJobViewPresenter;}
    }
}

public class ActivityView : BaseView
{
    public IActivityViewPresenter ActivityViewPresenter
    {
        get { this.Presenter as IActivityViewPresenter;}
    }
}

 

Lets assume that  a IBasePresenter property  is needed on BaseView. Now this property is inherited by JobView and ActivityView but if a reference of IJobViewPresenter object is needed in these derived classes then you need to type cast IBasePresenter property to IJobViewPresenter or IActivityPresenter or create JobViewPresenter and ActivityViewPresenter on derived classes (as shown above).

if you want to avoid type casting in derived classes and still have reference to IJobViewPresenter or IActivityViewPresenter and still have IBasePresenter in BaseView then follow this pattern

 

Create a generic BaseView<TPresenter> class as shown below and derived class will have a reference to IJobViewPresenter or IActivityViewPresenter

public class BaseView<TPresenter>
        where TPresenter: IBasePresenter
    {
        TPresenter Presenter { get; set; }
    }

    public class JobView: BaseView<IJobViewPresenter>
    {

    }

Categories: Uncategorized

Why C# doesn’t allow Type Covariance

April 2, 2010 3 comments
If you want to read more about Type Covariance then visit HERE. C# supports Type Covariance and 
Contravariance but it is only limited to delegates.
Lets create some interface to explain what I am talking about
  public interface ITimeEventHandler
    {
        string Open();
    }

    public interface IJobTimeEventHandler : ITimeEventHandler
    {
        string DeleteJob();
    }

    public interface IActivityTimeEventHandler : ITimeEventHandler
    {
        string DeleteActivity();
    }



    public interface ITimeEvent
    {
        ITimeEventHandler GetHandler();  
    }

    public interface IJobTimeEvent : ITimeEvent
    {
        int JobID { get;  }
    }
Now lets create a class which implements IJobTimeEvent
 
public class JobTimeEvent : IJobTimeEvent
    {
        public int JobID
        {
            get; internal set;

        }

        public IJobTimeEventHandler GetHandler()  {
 //Why can’t I return IJobTimeEventHandler instead of ITimeEventHandler
  return null; }
}
For Properties it doesn’t make that much sense but for methods it should be allowed. If Properties have setters then it 
could possibly result into runtime exception. 
For example
ITimeEvent te = new JobTimeEvent();
te.Handler = new ActivityTimeEventHandler(); //If Handler is a property on ITimeEvent
 
What is your opinion on this ?

Categories: Uncategorized

Visual Studio 2010 Beta (Architecture Explorer) – nice to have..

December 16, 2009 14 comments

Visual studio 2010 is going to have a new tool to help visualize the dependency graph and architecture of the application.

It is quite helpful in getting up to speed on a new project or a specific area of the application. There are some third party tools already available for this purpose but VS 2010 will  soon become the first option.

It can help you in how areas of code are related to each other, how a change will effect other areas and could also help in determining the complexity of code.

Here are some screen shots…

(Class level dependency)

 

(Methods and properties dependency)

Categories: Uncategorized
Follow

Get every new post delivered to your Inbox.