Thursday, December 9, 2010

File search: something I discovered in VS2010

Anyone who uses Visual Studio should be familiar with the Find in Files functionality (shortcut: Ctrl-Shift-F ).



Everyone has used it at some point, usually when you need to search all the files in your solution for a particular string. Those of you more adventurous may even have changed the file filter at the bottom, or searched using a regex. Pat yourself on the back, you are awesome.

Today i found a feature of it that has been there for a few years but i had never seen it before. This feature kicks ass. I used it to search specific folders on the file system that were outside of the solution. How many times have you thought to yourself, "hmmm.... where was that bit of code in that other project that did that certain thing...?", so you break out Windows File Explorer to search your base projects folder, only to be returned a bunch of crap? Well, you don't even have to leave your IDE to do it. Start up Find in Files, and on the Look in combo (that is usually set to Entire Solution or Current Document), click the ellipsis to the right of it:



and you will be presented with a dialog you never knew existed.



Just navigate your file system using the Available folders combo and its up-a-level button, and select whichever folders or drives you want to search from the listbox. Hit OK then Find All and Visual Studio will start searching for you.



Super user tips:
  • Don't forget that you can still use the file filter box, if searching large folder structures you may want to limit what files you are checking.
  • If you want to avoid that browse dialog, you can just enter a semi-colon delimited set of paths straight into the Look in combo
  • You can save a set of folders/paths for later use. In the browse dialog, select your paths, then enter a name for them in the Folder set combo and click Apply. You can then reselect that entry in later searches.

Friday, February 26, 2010

Streamlining property notifications in MVVM

Anyone doing Silverlight or WPF will know that the MVVM pattern is all the rage at the moment. So lots of people out there are now writing ViewModels to bind to their Views, which means they will be writing this sort of thing:
public string MyProperty
{
get { return _myProperty; }
set
{
bool changed = value != _myProperty;
if (changed)
{
_myProperty = value;
OnPropertyChanged("MyProperty");
}
}
}


When you have a ViewModel that has anything more than just a few properties, you end up having a LOT of code that while not an exact duplicate, it is doing the exact same thing to different arguments, which may or may not be of the same type. Then you multiply this problem by the number of Views you have, and the process of writing a ViewModel becomes very tedious indeed.

When you have the same code duplicated, you look to see if you can refactor it into a function, and the lines of duplicated code become a call to that new function. And when you are doing the exact same thing to different types, you look to see if you can employ generics.

To solve this issue i came up with the following:
protected void SetProperty(ref T newValue, ref T currentValue, bool notify, string propertyName, params string[] additionalProperties)
{
bool changed = notify && ((newValue != null && !newValue.Equals(currentValue)) || (newValue == null && currentValue != null));
currentValue = newValue;
if (changed)
{
OnPropertyChanged(propertyName);
if (additionalProperties != null)
foreach (string additionalProperty in additionalProperties)
OnPropertyChanged(additionalProperty);
}
}


It's not rocket science, and others have probably come up with the same kind of function, but i love it because it now saves me so much time and eliminates so much repetition. I include this function in to a base class that all my ViewModels inherit from, here it is with a sample on how to use it:
public class ViewModelBase : INotifyPropertyChanged
{

protected void SetProperty(ref T newValue, ref T currentValue, bool notify, string propertyName, params string[] additionalProperties)
{
bool changed = notify && ((newValue != null && !newValue.Equals(currentValue)) || (newValue == null && currentValue != null));
currentValue = newValue;
if (changed)
{
OnPropertyChanged(propertyName);

if (additionalProperties != null)
foreach (string additionalProperty in additionalProperties)
OnPropertyChanged(additionalProperty);
}
}

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

public event PropertyChangedEventHandler PropertyChanged;
}

public class MyRealViewModel : ViewModelBase
{
public int NumberOfItems
{
get { return _numItems; }
set { SetProperty(ref value, ref _numItems, true, "NumberOfItems"); }
}

public bool SomeKindOfFlag
{
get { return _flag; }
set { SetProperty(ref value, ref _flag, false, ""); }
}

public LightSabre WeaponOfChoice
{
get { return _weapon; }
set { SetProperty(ref value, ref _weapon, true, "WeaponOfChoice", "SomeKindOfFlag", "NumberOfItems"); }
}

private bool _flag;
private int _numItems;
private LightSabre _weapon;
}

public class LightSabre
{
public string LightSabreName { get; set; }

public override bool Equals(object obj)
{
if (obj != null && obj as LightSabre != null)
return ((LightSabre)obj).LightSabreName == this.LightSabreName;

return false;
}
}