Monday, April 26, 2010

Change Selected Text (highlighted text) in Visual Studio 2010

I always optimize my settings when using Remote Desktop, but unfortunately it has a few bad side effects. Although I didn’t have this problem in Visual Studio 2008, with 2010 I find that selected text is almost impossible to see. For some bizarre reason, it is only shows highlighting once I change focus.

Tool –> Options –> Environment –> Fonts and Colors –> Display items: –> Selected Text

image 

Before (I am not making this up!)

image

After (Yay!)

image

Force the browser to scroll to the top using Silverlight

I recently had an master / details scenario where the details popup was much larger than the master control. If I all the way down in the details popup and then returned to the master control, the browser would maintain the scrolling position and the master control would no longer be visible unless I scrolled up. Fortunately Silverlight provides a mechanism for calling JavaScript functions. ;)

Steps:

1.  Add a top anchor tag to the top of the HTML page rendering your Silverlight object.

     <a name=”top” />

2.  Add a JavaScript function to the same page.

     function ScrollToTop { location.href=”#top”; }

3.  Use the following code to call from Silverlight:

     using System.Windows.Browser;
     …
     HtmlPage.Window.Invoke(“ScrollToTop”);

Note: I tried using “windows.scroll(0, 0)” in my JavaScript function to no avail, but using an anchor tag worked just fine.

Friday, April 16, 2010

Change tab order of documents being opened in Visual Studio 2010

At some point between 2003 and 2008, Microsoft changed the default order of where tabs appeared in Visual Studio. In the old version, new document tabs would appear to the right. The new version switched this behavior. I always preferred the old order and now it is an option.

Tools –> Options –> Environment –> Documents

image

Thursday, April 15, 2010

Creating a globally accessible property in a Silverlight application

You have created a Silverlight application and have a property that you want to make globally available. Although you could add it to the Resources collection of your App object, you really want to know every time the property has changed. If you were in a UserControl, you could create dependency properties that allow you to listen for PropertyChanged events, but these would not be global. Handling this at the application level would be best, but because App doesn’t derive from DependencyObject like UserControls, you cannot implement the SetValue and GetValue methods that are required for writing dependency properties.

It turns out that the solution ends up being easier than you think. Essentially you will be encapsulating an object within the App that implements INotifyPropertyChanged. You will then add PropertyChanged events anywhere you want to know where the property changes.

Steps:
1. Create a new Silverlight Application.
2. Add a new class that implements INotifyPropertyChanged. I will call mine “GroupNameObject”. Make sure to add a System.ComponentModel using statement.

using System.ComponentModel;

public class GroupNameObject : INotifyPropertyChanged
{
private string groupName;

public event PropertyChangedEventHandler PropertyChanged;

public GroupNameObject(string value)
{
this.groupName = value;
}

public string GroupName
{
get
{
return groupName;
}
set
{
groupName= value;
OnPropertyChanged("GroupName");
}
}

protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

3. In your App class add a public property of the type you just created.

public GroupNameObject GroupName = new GroupNameObject("Admin");

4. Now in any UserControl constructor, you can subscribe to the PropertyChanged event and add an event handler.

public MainPage()
{
InitializeComponent();
//Notice how App.Current can be cast to your App instance.
((App)App.Current).GroupName.PropertyChanged +=
new System.ComponentModel.PropertyChangedEventHandler(GroupName_PropertyChanged);
}

void GroupName_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//Disable update button if group is viewer
if(((GroupameObject)sender).GroupName == “Viewer”)
{
updateButton.IsEnabled = false;
}

}

Now any time the property gets changed, you can listen to it and act accordingly. Obviously you would use an object or enum instead of a string here, but I kept it easy for illustration purposes. Also, if you are using MVVM, you should handle this in your ViewModel classes. Happy coding!

Tuesday, April 13, 2010

Create enum based Collection Dependency Properties and set them declaratively in XAML

I was recently updating a Silverlight web part that involved a very complicated form. I came across a scenario where I needed to determine a user’s SharePoint group and then disable or enable a user control according to their permissions. I already had code that passed the user’s credentials and mapped the custom SharePoint groups to an enum. Since there were many databound controls with many different permissions, the main goal was to be able to easily set these permissions declaratively within XAML.

Ultimately, I wanted something that looked like the following. In this example, only a Manager or Supervisor have access to edit the control. The CurrentGroup property is databound and if it returned anything other than Manager or Supervisor, the control would be disabled.

        <localCtrl:MyPermissionTextBox x:Name="permissionCtrl" CurrentGroup="{Binding CurrentGroup}">
<
localCtrl:MyPermissionTextBox.PermissionGroups>
<
localCtrl:PermissionGroupItem Group="Manager" />
<
localCtrl:PermissionGroupItem Group="Supervisor" />
</
localCtrl:MyPermissionTextBox.PermissionGroups>
</
localCtrl:MyPermissionTextBox>


In a nutshell, you will want to do the following steps:



1. Create an item class that encapsulates your enum and stores it as a property.

2. Create a collection class that derives from ObservableCollection<T> (where T is the item class type). Add a read-only property that retrieves your list of enums into a a generic list.


3. Add a UserControl that has two dependency properties: one for the collection class, and one for the current group.


4. In the UserControl’s Loaded event handler, disable or enable the control by checking if the current group is in the list of groups for the control.


5. Add the UserControl to a layout page and set all of the properties in XAML.



Permission UserControl XAML


1. Add a Silverlight UserControl to your project. I named mine “MyPermissionTextBox”.

2. Update the XAML to include a Loaded event handler for the UserControl and a TextBox control with the name “MyControl”.



<UserControl x:Class="MyProject.Controls.MyPermissionTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" Loaded="UserControl_Loaded">
<
Grid x:Name="LayoutRoot" Background="White">
<
TextBox Name="MyControl" Width="150" Height="20" />
</
Grid>
</
UserControl>



Permission UserControl Code Behind



using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace MyProject.Controls
{
public enum PermissionGroup { Viewer, Member, Manager, SrManager, Supervisor, Admin }

public partial class MyPermissionTextBox : UserControl
{
public static readonly DependencyProperty PermissionGroupsProperty =
DependencyProperty.Register("PermissionGroups", typeof(PermissionGroupItemCollection), typeof(MyPermissionTextBox),
new PropertyMetadata(null, OnPermissionGroupsPropertyChanged));

private static void OnPermissionGroupsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyPermissionTextBox source = (MyPermissionTextBox)d;
source.PermissionGroups = (PermissionGroupItemCollection)e.NewValue;
}

public PermissionGroupItemCollection PermissionGroups
{
get
{
if (GetValue(PermissionGroupsProperty) == null)
{
return new PermissionGroupItemCollection();
}
else
{
return (PermissionGroupItemCollection)GetValue(PermissionGroupsProperty);
}
}
set
{
if (value is PermissionGroupItemCollection)
{
MyControl.IsEnabled = ((PermissionGroupItemCollection)value).Values.Contains(CurrentGroup);
SetValue(PermissionGroupsProperty, value);
}
else
{
MyControl.IsEnabled = false;
}
}
}

public static readonly DependencyProperty CurrentGroupProperty =
DependencyProperty.Register("CurrentGroup", typeof(PermissionGroup), typeof(MyPermissionTextBox),
new PropertyMetadata(PermissionGroup.Viewers, OnCurrentGroupPropertyChanged));

private static void OnCurrentGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyPermissionTextBox source = (MyPermissionTextBox)d;
source.CurrentGroup = (PermissionGroup)e.NewValue;
}

public PermissionGroup CurrentGroup
{
get
{
return (PermissionGroup)GetValue(CurrentGroupProperty);
}
set
{
SetValue(CurrentGroupProperty, value);
}
}

public MyPermissionTextBox()
{
InitializeComponent();
PermissionGroups = new PermissionGroupItemCollection();
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
MyControl.IsEnabled = PermissionGroups.Values.Contains(CurrentGroup);
}
}

public class PermissionGroupItem
{
public PermissionGroup Group { get; set; }
}

public class PermissionGroupItemCollection : ObservableCollection<PermissionGroupItem>
{
public List<PermissionGroup> Values
{
get
{
return (from n in this.Items select n.Group).ToList();
}
}
}
}



Test UserControl XAML



Note: You will need to handle the Binding for CurrentGroup. In this example I have simply hard-coded. In this case the control would be disabled as the Viewer is not in the list of Permissions.




<UserControl x:Class="MyProject.Controls.Test"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:MyProject"

xmlns:localCtrl="clr-namespace:MyProject.Controls" Height="300"Width="300">

<
Grid x:Name="LayoutRoot"Background="White"HorizontalAlignment="Stretch">

<
localCtrl:MyPermissionTextBox x:Name="permissionCtrl"CurrentGroup="Viewer">

<
localCtrl:MyPermissionTextBox.PermissionGroups>

<
localCtrl:PermissionGroupItem Group="Manager" />

<
localCtrl:PermissionGroupItem Group="Supervisor" />

</
localCtrl:MyPermissionTextBox.PermissionGroups>

</
localCtrl:MyPermissionTextBox>

<
TextBlock FontSize="10">

<
TextBlock.Style>

<
Style>

<
SetterProperty="FontSize"Value="10" />

</
Style>

</
TextBlock.Style>

</
TextBlock>

</
Grid>

</
UserControl>



Note: All code done in Visual Studio 2010 RTM.