HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Code Explorer View Models

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
codeexplorerviewmodels

Problem

Continuing the series of Code Explorer posts, here is the collection of view models for the tree nodes:

This is the interface for nodes with a declaration.

public interface ICodeExplorerDeclarationViewModel
{
    Declaration Declaration { get; }
}


And here is the abstract view model they are all based on:

```
public abstract class CodeExplorerItemViewModel : ViewModelBase
{
private List _items = new List();
public List Items
{
get { return _items; }
protected set
{
_items = value;
OnPropertyChanged();
}
}

public bool IsExpanded { get; set; }

public abstract string Name { get; }
public abstract string NameWithSignature { get; }
public abstract BitmapImage CollapsedIcon { get; }
public abstract BitmapImage ExpandedIcon { get; }
public abstract CodeExplorerItemViewModel Parent { get; }

public abstract QualifiedSelection? QualifiedSelection { get; }

public CodeExplorerItemViewModel GetChild(string name)
{
foreach (var item in _items)
{
if (item.Name == name)
{
return item;
}
var result = item.GetChild(name);
if (result != null)
{
return result;
}
}

return null;
}

public Declaration GetSelectedDeclaration()
{
return this is ICodeExplorerDeclarationViewModel
? ((ICodeExplorerDeclarationViewModel)this).Declaration
: null;
}

public void AddChild(CodeExplorerItemViewModel item)
{
_items.Add(item);
}

public void ReorderItems(bool sortByName, bool sortByType)
{
if (sortByType)
{
Items = sortByName
? Items.OrderBy(o => o, new CompareByType()).ThenBy(t => t, new CompareByName()).ToList()
: Items.OrderBy(o => o, new CompareByType()).ThenBy(t => t, new CompareBySelection()).To

Solution

GetSelectedDeclaration is ugly and a little bit uncomprehensive.
CodeExplorerItemViewModel does not implement ICodeExplorerDeclarationViewModel, so this method can only return something on a subclass
of it like CodeExplorerProjectViewModel. I would prefer to have a virtual method and override it.

//on `CodeExplorerItemViewModel`
public virtual Declaration GetSelectedDeclaration()
{
    return null;
}

//on `CodeExplorerProjectViewModel `
public override Declaration GetSelectedDeclaration()
{
    return Declaration;
}


ReorderItems is ok but there's room for improvement.
What you know is that the OrderBy may be performed by any comparer and it may be needed a ThenBy if sortByType is selected.
You also always need one instance of CompareByName or CompareBySelection.
I sugest an implementation where you start by instatiating the right comparer:

public void ReorderItems(bool sortByName, bool sortByType)
{
    var comparer = sortByName ? new CompareByName() : new CompareBySelection();

    if(sortByType){
        Items = Items
            .OrderBy(o => o, new CompareByType())
            .ThenBy(comparer)
            .ToList();

    }else{
        Items = Items
            .OrderBy(o => o, comparer))
            .ToList();
    }
}


Your AddNodesToTree could use a variable to store the nodes before adding them to folder.

var nodes = items.Where(item => parents.Contains(item) || 
                parents.Any(parent =>
                    (item.ParentDeclaration != null && item.ParentDeclaration.Equals(parent)) ||
                    item.ComponentName == parent.ComponentName)
                ).ToList()

folder.AddNodes(nodes);


CodeExplorerItemViewModel could have a Root property that would return the first node, sou you wouldn't have to write the while on CodeExplorerComponentViewModel-

Code Snippets

//on `CodeExplorerItemViewModel`
public virtual Declaration GetSelectedDeclaration()
{
    return null;
}

//on `CodeExplorerProjectViewModel `
public override Declaration GetSelectedDeclaration()
{
    return Declaration;
}
public void ReorderItems(bool sortByName, bool sortByType)
{
    var comparer = sortByName ? new CompareByName() : new CompareBySelection();

    if(sortByType){
        Items = Items
            .OrderBy(o => o, new CompareByType())
            .ThenBy(comparer)
            .ToList();

    }else{
        Items = Items
            .OrderBy(o => o, comparer))
            .ToList();
    }
}
var nodes = items.Where(item => parents.Contains(item) || 
                parents.Any(parent =>
                    (item.ParentDeclaration != null && item.ParentDeclaration.Equals(parent)) ||
                    item.ComponentName == parent.ComponentName)
                ).ToList()

folder.AddNodes(nodes);

Context

StackExchange Code Review Q#129507, answer score: 3

Revisions (0)

No revisions yet.