FIX: TabControl in WPF Shows wrong tab if Active Tab is Invisible

You want to dynamically show or hide tabs in WPF. Say, some only show up if a certain option is set. Well, it shows anyway if its the first tab. Stupid. Here is an attached property to fix that.

Based on code from http://www.codeproject.com/Articles/349140/WPF-TabControl-focus-behavior-with-invisible-tabs

 

using System;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
namespace Seekford
{/// <summary>Behaviors for TabControl.
    /// </summary>
    public class TabControlBehavior
    {
        /// <summary>Whether to focus the first visible tab.
        /// </summary>
        /// <remarks>Setting the FocusFirstVisibleTab
        /// attached property to true will focus the next visible tab when
        /// the current selected tab's Visibility property is set to Collapsed or Hidden.</remarks>
        public static readonly DependencyProperty FocusFirstVisibleTabProperty =
            DependencyProperty.RegisterAttached("FocusFirstVisibleTab", typeof(bool),
                typeof(TabControlBehavior),
                new FrameworkPropertyMetadata(OnFocusFirstVisibleTabPropertyChanged));
        /// <summary>Gets the focus first visible tab value of the given element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        public static bool GetFocusFirstVisibleTab(TabControl element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            return (bool)element.GetValue(FocusFirstVisibleTabProperty);
        }
        /// <summary>Sets the focus first visible tab value of the given element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="value">if set to <c>true</c> [value].</param>
        public static void SetFocusFirstVisibleTab(TabControl element, bool value)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            element.SetValue(FocusFirstVisibleTabProperty, value);
        }
        /// <summary>Determines whether the value of the dependency property <c>IsFocused</c> has change.
        /// </summary>
        /// <param name="d">The dependency object.</param>
        /// <param name="e">The  instance containing the event data.</param>
        private static void OnFocusFirstVisibleTabPropertyChanged(
                DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var tabControl = d as TabControl;
            if (tabControl != null)
            {
                // Attach or detach the event handlers.
                tabControl.IsSynchronizedWithCurrentItem = true;
                if ((bool)e.NewValue)
                {
                    var collection = tabControl.Items as INotifyCollectionChanged;
                    if (collection != null)
                    {
                        collection.CollectionChanged +=
                          new NotifyCollectionChangedEventHandler(TabControl_Items_CollectionChanged);
                    }
                }
                else
                {
                    // Disable the attached behavior.
                    var collection = tabControl.Items as INotifyCollectionChanged;
                    if (collection != null)
                    {
                        collection.CollectionChanged -=
                          new NotifyCollectionChangedEventHandler(TabControl_Items_CollectionChanged);
                    }
                    // Detach handlers from the tab items.
                    foreach (var item in tabControl.Items)
                    {
                        TabItem tab = item as TabItem;
                        if (tab != null)
                        {
                            tab.IsVisibleChanged -=
                              new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged);
                        }
                    }
                }
            }
        }
        /// <summary>Handles the CollectionChanged event of the TabControl.Items collection.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see
        ///    cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/>
        ///    instance containing the event data.</param>
        static void TabControl_Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // Attach event handlers to each tab so that when the Visibility property changes of the selected tab,
            // the focus can be shifted to the next (or previous, if not next tab available) tab.
            var collection = sender as ItemCollection;
            if (collection != null)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                    case NotifyCollectionChangedAction.Remove:
                    case NotifyCollectionChangedAction.Replace:
                        // Attach event handlers to the Visibility and IsEnabled properties.
                        if (e.NewItems != null)
                        {
                            foreach (var item in e.NewItems)
                            {
                                TabItem tab = item as TabItem;
                                if (tab != null)
                                {
                                    tab.IsVisibleChanged +=
                                      new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged);
                                }
                            }
                        }
                        // Detach event handlers from old items.
                        if (e.OldItems != null)
                        {
                            foreach (var item in e.OldItems)
                            {
                                TabItem tab = item as TabItem;
                                if (tab != null)
                                {
                                    tab.IsVisibleChanged -=
                                      new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged);
                                }
                            }
                        }
                        break;
                    case NotifyCollectionChangedAction.Reset:
                        // Attach event handlers to the Visibility and IsEnabled properties.
                        foreach (var item in collection)
                        {
                            TabItem tab = item as TabItem;
                            if (tab != null)
                            {
                                tab.IsVisibleChanged +=
                                  new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged);
                            }
                        }
                        break;
                    case NotifyCollectionChangedAction.Move:
                    default:
                        break;
                }
                // Select the first element if necessary.
                if (collection.Count > 0 && collection.CurrentItem == null)
                {
                    foreach (var item in collection)
                    {
                        if ((item as TabItem).Visibility == Visibility.Visible)
                        {
                            collection.MoveCurrentTo(item);
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>Handles the IsVisibleChanged event of the tab item.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see
        ///   cref="System.Windows.DependencyPropertyChangedEventArgs"/>
        ///   instance containing the event data.</param>
        static void TabItem_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            TabItem tab = sender as TabItem;
            if (tab != null)
            {
                //ensure active tab is visible
                TabControl tabControl = tab.Parent as TabControl;
                if (tabControl != null)
                {
                    bool goforward = true;
                    while (tabControl.SelectedItem == null || (!(tabControl.SelectedItem as TabItem).IsVisible))
                    {
                        if (goforward)
                        {
                            goforward = tabControl.Items.MoveCurrentToNext();
                        }
                        else
                        {
                            if (!tabControl.Items.MoveCurrentToPrevious())
                                break;//nothing is visible
                        }
                    }
                }
            }
        }
    }
}

 

Happy Coding

How to center or right align the Header in the WPF RadGridView by Telerik?

Telerik is not the best at providing documentation on how to do things, so I figured I would write some of the more mundane tasks that took me a few minutes thought.

Here, I needed to center my headers. It is easy but only if you know all the magic words. If you don’t, it is pretty hard.

Here is how you do it. A simple style.

Snippet

        <telerik:RadTreeListView ItemsSource="{Binding Nodes}" AutoGenerateColumns="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                               IsExpandedBinding="{Binding IsExpanded,Mode=TwoWay}"                                 
                               Name="mainTree"
                               SelectionUnit="FullRow"                                 
                               RowIndicatorVisibility="Collapsed"
                               CanUserResizeColumns="False"
                             SelectedItem="{Binding SelectedNode,Mode=TwoWay}"
                               >
            <telerik:RadTreeListView.Resources>
                <Style BasedOn="{StaticResource {x:Type telerik:GridViewHeaderCell}}" TargetType="{x:Type  telerik:GridViewHeaderCell}">
                    <Setter Property="HorizontalContentAlignment" Value="Center"/>
                </Style>
            </telerik:RadTreeListView.Resources>
......

Happy Coding!

How to run a batch file with administrator priveleges with automatic elevation

Do you have build scripts that require you run commands elevated. Do you forget to click run as admin then you get errors halfway through a 20 minute build?

Well, I did all the damn time. I found this script change and it works awesome so I figured I would share with the class.


if _%1_==_payload_ goto :payload

:getadmin
echo %~nx0: elevating self
set vbs=%temp%\getadmin.vbs
echo Set UAC = CreateObject^(“Shell.Application”^) >> “%vbs%”
echo UAC.ShellExecute “%~s0”, “payload %~sdp0 %*”, “”, “runas”, 1 >> “%vbs%”
“%temp%\getadmin.vbs”
del “%temp%\getadmin.vbs”
goto :eof

:payload
echo %~nx0: running payload with parameters:
echo %*
echo —————————————————
cd /d %2
shift
shift
rem put your code here
rem e.g.: perl myscript.pl %1 %2 %3 %4 %5 %6 %7 %8 %9
rem SEEKFORD – added code for build. I left in above for guys that need params in this blog post.
@cd /d “%~dp0”
set msbuilddir=C:\program Files (x86)\MSBuild\12.0\Bin
“%msbuilddir%\msbuild” “%CD%\SSI.Build” /t:Build /p:Configuration=Debug;ReferencePath=%CD%\..\bin
goto :eof

 

This is a modified version that I got from here (thanks to Alois Mahdal) that adds in how to build using msbuild.

Happy Coding! or emmm.. Happy Building!!

WPF Validation Errors not showing on initial load of control or window

I was setting validation errors on the initial load of my view model, and to my annoyance the window would show up like everything was great. The validation code was definitely running, the HasErrors was true, the dictionaries were filled with the errors but the form was like, “What errors?”  This irritated me. Well, WPF is stupid in this regard and doesn’t handle things properly. If you are like me, you set your datacontext after creating the view. Well, that is the logical way, but if you want validation you need to slightly alter that. I found a work around that fixes the problem, but is a little more annoying. Simply put, pass in your VM to the constructor of the view. Cache that, then set your DataContext(DC) on the load event. Sample code below:

public partial class AcceptRejectViewOldMeetsNew : UserControl
 {
   private object dcToSet = null;
   public AcceptRejectViewOldMeetsNew(object dc)
  {
    InitializeComponent();
    dcToSet = dc;
    this.Loaded += AcceptRejectViewOldMeetsNew_Loaded;
  }
  void AcceptRejectViewOldMeetsNew_Loaded(object sender, System.Windows.RoutedEventArgs e)
  {
    DataContext = dcToSet;
    }
 }

Happy Coding!

How to access legacy forms checkboxes and ActiveX checkboxes in Word using C#!

Apparently, doing this simple task is not well documented. None of my searches lead to anything useful, so here is what I wrote for how to handle the search for all checkboxes in a word document then set them all to false. Obviously, you can use this to get values, launch rockets, whatever it is you want to do.

[csharp]
//go through legacy fields.
foreach (FormField c in vstoDoc.FormFields)
{
try
{
if (c.Type == WdFieldType.wdFieldFormCheckBox)
{
if (c.CheckBox.Value)
c.CheckBox.Value = false;
}
}
catch { }
}

//go through the activex fields.
foreach(Field f in vstoDoc.Fields)
{
if (f.Type == WdFieldType.wdFieldOCX)
{
try
{
if (f.OLEFormat != null)
{
if(f.OLEFormat.ProgID.ToLowerInvariant().Contains("checkbox"))
{
if(f.OLEFormat.Object.Value)
f.OLEFormat.Object.Value = false;
}
}
}
catch { }
}

}
[/csharp]

I am sure you figured out my variable vstoDoc is the document. If not, well, McDonalds always need a new fry cook.

Happy Coding!

How to unshelve a shelveset from one branch into another branch!

I was doing a lot of work in our Main branch for a new version of our software. Lo and behold, this iteration requires we work on both the future and current version at the same time. Only a few of us are on the new version, therefore the Main branch code branched into a future version branch. Ugh. All my work sitting in a shelveset for the Main branch.

Moving it sounds painful to me. Luckily there is a really cool automated method provided by TFS. You simply need to deal with playing with the command line.

This guy did a good job giving an overview:

http://geekswithblogs.net/TarunArora/archive/2011/06/06/unshelve-shelveset-created-from-one-branch-to-another.aspx

This guy was easier for me to read:

http://chunkyinterface.wordpress.com/2012/02/17/migrating-shelvesets-between-branches-in-tfs/

tfpt unshelve - Unshelve into workspace with pending changes

Allows a shelveset to be unshelved into a workspace with pending changes.
Merges content between local and shelved changes. Allows migration of shelved
changes from one branch into another by rewriting server paths.

Usage: tfpt unshelve [shelvesetname[;username]] [/nobackup]
[/migrate /source:serverpath /target:serverpath]

shelvesetname The name of the shelveset to unshelve
/nobackup Skip the creation of a backup shelveset
/migrate Rewrite the server paths of the shelved items
(for example to unshelve into another branch)
/source:serverpath Source location for path rewrite (supply with /migrate)
/target:serverpath Target location for path rewrite (supply with /migrate)

Here is an example I used in action:

tfpt unshelve "Native Templates Work" /migrate /source:$/Source/Main /target:$/Source/Main-6.0

Happy coding!

Speed up WPF XAML Editor in Visual Studio 2012

Tired of the stupid XAML editor being so slow. Mine freezes, locks up and is otherwise unruly. I didn’t seem to have a choice if I wanted intellisense in Visual Studio before 2012. Well, apparently they fixed the source code editor in 2012 to have working intellisense so there is now a viable option for ditching the buggy standard designer view.

Yes, even if you are in the XAML tab full screen, the stupid designer is still working and crunching on everything you type and blowing its lid at all your inflight incorrect changes.

How do you fix it, easy. Right click your xaml file in the Solution Explorer(filename, not the file contents) and choose Open With…. Pick Source Code Editor. Click the use as default option. Hit ok.

Done. Enjoy not wanting to throw your computer after losing your changes repeatedly due to the designer full on crashing.

Happy Coding!

Want pictures, its the last section of this guys entry. Good reading. The first two were what I had used before since the third wasn’t viable before 2012.

http://blog.spinthemoose.com/2013/03/24/disable-the-xaml-designer-in-visual-studio/

How to add a picture to a worksheet in Word and Excel using VSTO with c# and autosize

Here is a really simple example of adding a picture without really needing to know the dimensions of the image. Excel uses points which is pretty annoying, since pics are in pixels….duh… I put in the sizes for my pics, but you could use any number since we repair it with the scale calls. Anyway, here it is. Word vstoDoc is my document.

[csharp]
//push resource to disk.
var path = Path.GetDirectoryName(vstoDoc.FullName);
var fn = Path.Combine(path,"rfn.png");
//insert the fun fact box at top.
var pic = vstoDoc.Shapes.AddPicture(fn,false,true,5,5,455/1.0,162/1.0);
pic.Name = ROLLFORWARDSHAPENAME;
pic.ScaleHeight(1, MsoTriState.msoTrue);
pic.ScaleWidth(1, MsoTriState.msoTrue);
[/csharp]

Here is Excel. vstoSheet is my Worksheet. I loop through them to add pics.

[csharp]
//push resource to disk.
var path = Path.GetDirectoryName(vstoDoc.FullName);
var fn = Path.Combine(path,"rfn.png");
var pic = vstoSheet.Shapes.AddPicture(fn, MsoTriState.msoFalse, MsoTriState.msoTrue, 5, 5, 231 * 72 / 96, 317 * 72 / 96);
pic.Name = ROLLFORWARDSHAPENAME;
pic.Locked = false;
pic.ScaleHeight(1, MsoTriState.msoTrue);
pic.ScaleWidth(1, MsoTriState.msoTrue);
[/csharp]

Happy Coding!

How to programmatically change your Windows domain password using C# (.NET)

Ever wanted to write a program that would change your password for you? Why on earth would you want this? Well, imagine you have a password policy that requires you to change your password every X days. Well, maybe you like your password and think it dumb to have to keep changing it. Maybe you would forget your new password and resort to writing it down.

Ideally, you should come up with a good password to begin with, then changing it would not be really necessary. Unless of course you are under attack by the Chinese.

So, I wrote a program that changes the password in code. Moreover, it does it multiple times then the puts it back to the original. My problem solved. Here is the code for your education and amusement. Now that you know how to change your password, will you use this for purposes of good or evil? Try leaving the world a better place.

[csharp]
using System;
using System.DirectoryServices.AccountManagement;
using System.Security.Principal;
using System.Windows.Forms;

namespace KeepMyPassword
{
public partial class fKeepMyPassword : Form
{
public fKeepMyPassword()
{
InitializeComponent();
}

private void cmdChangePassword_Click(object sender, EventArgs e)
{
txtCurrentPassword.Enabled = false;
cmdChangePassword.Enabled = false;
try
{
ChangePassword(txtCurrentPassword.Text);
}
catch (Exception ex)
{
MessageBox.Show(&quot;An error occurred:&quot; + ex.Message);
}

txtCurrentPassword.Enabled = true;
cmdChangePassword.Enabled = true;
}

private string currentPassword;
private void ChangePassword(string p)
{
var currentUser = WindowsIdentity.GetCurrent().Name;
currentPassword = p;
try
{
using (var context = new PrincipalContext(ContextType.Domain))
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, currentUser))
{
for (int ix = 0; ix &lt; 10; ix++)
{
var newPassword = p + (char)(((int)’a’) + ix);
user.ChangePassword(currentPassword, newPassword);
currentPassword = newPassword;
}
user.ChangePassword(currentPassword, p);
currentPassword = p;
MessageBox.Show(&quot;Password has been reset and back to original&quot;);
}
//set back to normal
}
catch (Exception ex)
{
MessageBox.Show(&quot;An error occurred:&quot; + ex.Message + &quot;nYour password is now: &quot; + currentPassword);
}
}
}
}

[/csharp]

Happy Coding!

 

KeepMyPassword <- you can download the compiled exe if you wish. Needs .NET 4.0 to run.