Display traits in tree view with check boxes
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xunit.runner.wpf
|
||||
{
|
||||
public static partial class Extensions
|
||||
{
|
||||
private class FuncComparer<T> : IComparer<T>
|
||||
{
|
||||
private readonly Func<T, T, int> _comparison;
|
||||
|
||||
public FuncComparer(Func<T, T, int> comparison)
|
||||
{
|
||||
_comparison = comparison;
|
||||
}
|
||||
|
||||
public int Compare(T x, T y) => _comparison(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace xunit.runner.wpf
|
||||
{
|
||||
public static class Extensions
|
||||
public static partial class Extensions
|
||||
{
|
||||
public static void AddRange<TList, TEnumerable>(this ICollection<TList> list, IEnumerable<TEnumerable> items) where TEnumerable : TList
|
||||
{
|
||||
@@ -24,5 +21,80 @@ namespace xunit.runner.wpf
|
||||
list.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static int BinarySearch<T, TValue>(this ObservableCollection<T> collection, int index, int length, TValue value, IComparer<TValue> comparer, Func<T, TValue> selector)
|
||||
{
|
||||
comparer = comparer ?? Comparer<TValue>.Default;
|
||||
|
||||
var low = index;
|
||||
var high = (index + length) - 1;
|
||||
|
||||
while (low <= high)
|
||||
{
|
||||
var mid = low + ((high - low) / 2);
|
||||
var comp = comparer.Compare(selector(collection[mid]), value);
|
||||
|
||||
if (comp == 0)
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
|
||||
if (comp < 0)
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ~low;
|
||||
}
|
||||
|
||||
public static int BinarySearch<T, TValue>(this ObservableCollection<T> collection, TValue value, IComparer<TValue> comparer, Func<T, TValue> selector)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, comparer, selector);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T, TValue>(this ObservableCollection<T> collection, int index, int length, TValue value, Func<TValue, TValue, int> comparison, Func<T, TValue> selector)
|
||||
{
|
||||
return collection.BinarySearch(index, length, value, new FuncComparer<TValue>(comparison), selector);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T, TValue>(this ObservableCollection<T> collection, TValue value, Func<TValue, TValue, int> comparison, Func<T, TValue> selector)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, new FuncComparer<TValue>(comparison), selector);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T, TValue>(this ObservableCollection<T> collection, TValue value, Func<T, TValue> selector)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, comparer: null, selector: selector);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T>(this ObservableCollection<T> collection, int index, int length, T value, IComparer<T> comparer)
|
||||
{
|
||||
return collection.BinarySearch(index, length, value, comparer, x => x);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T>(this ObservableCollection<T> collection, T value, IComparer<T> comparer)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, comparer, x => x);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T>(this ObservableCollection<T> collection, T value)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, Comparer<T>.Default, x => x);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T>(this ObservableCollection<T> collection, int index, int length, T value, Func<T, T, int> comparison)
|
||||
{
|
||||
return collection.BinarySearch(index, length, value, new FuncComparer<T>(comparison), x => x);
|
||||
}
|
||||
|
||||
public static int BinarySearch<T>(this ObservableCollection<T> collection, T value, Func<T, T, int> comparison)
|
||||
{
|
||||
return collection.BinarySearch(0, collection.Count, value, new FuncComparer<T>(comparison), x => x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,7 @@ namespace xunit.runner.wpf
|
||||
|
||||
protected virtual void OnItemChanged(T sender, PropertyChangedEventArgs args)
|
||||
{
|
||||
var itemChanged = this.ItemChanged;
|
||||
if (itemChanged != null)
|
||||
{
|
||||
itemChanged(sender, args);
|
||||
}
|
||||
this.ItemChanged?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
private TFilterArg filterArgument;
|
||||
@@ -187,11 +183,7 @@ namespace xunit.runner.wpf
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
var collectionChanged = this.CollectionChanged;
|
||||
if (collectionChanged != null)
|
||||
{
|
||||
collectionChanged(this, args);
|
||||
}
|
||||
this.CollectionChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
|
||||
@@ -119,13 +119,13 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
||||
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
|
||||
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Reload" Command="{Binding AssemblyReloadCommand}" />
|
||||
@@ -139,29 +139,44 @@
|
||||
|
||||
<Label Content="Traits:"
|
||||
Grid.Row="4" />
|
||||
<ListBox Grid.Row="5"
|
||||
ItemsSource="{Binding Traits}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:TraitViewModel">
|
||||
<TextBlock Text="{Binding DisplayName}" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
|
||||
|
||||
<TreeView Grid.Row="5"
|
||||
ItemsSource="{Binding Traits}">
|
||||
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type vm:TraitViewModel}"
|
||||
ItemsSource="{Binding Children}">
|
||||
|
||||
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Checked">
|
||||
<cmd:EventToCommand Command="{Binding DataContext.TraitCheckedChangedCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
|
||||
<i:EventTrigger EventName="Unchecked">
|
||||
<cmd:EventToCommand Command="{Binding DataContext.TraitCheckedChangedCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</CheckBox>
|
||||
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
|
||||
<TreeView.ItemContainerStyle>
|
||||
<Style TargetType="TreeViewItem">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ContextMenu>
|
||||
</TreeView.ItemContainerStyle>
|
||||
|
||||
<TreeView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Clear" Command="{Binding TraitsClearCommand}" />
|
||||
</ContextMenu>
|
||||
</ListBox.ContextMenu>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<cmd:EventToCommand Command="{Binding TraitSelectionChangedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBox>
|
||||
</TreeView.ContextMenu>
|
||||
|
||||
</TreeView>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace xunit.runner.wpf.ViewModel
|
||||
this.WindowLoadedCommand = new RelayCommand(OnExecuteWindowLoaded);
|
||||
this.RunCommand = new RelayCommand(OnExecuteRun, CanExecuteRun);
|
||||
this.CancelCommand = new RelayCommand(OnExecuteCancel, CanExecuteCancel);
|
||||
this.TraitSelectionChangedCommand = new RelayCommand(OnExecuteTraitSelectionChanged);
|
||||
this.TraitCheckedChangedCommand = new RelayCommand<TraitViewModel>(OnExecuteTraitCheckedChanged);
|
||||
this.TraitsClearCommand = new RelayCommand(OnExecuteTraitsClear);
|
||||
this.AssemblyReloadCommand = new RelayCommand(OnExecuteAssemblyReload, CanExecuteAssemblyReload);
|
||||
this.AssemblyReloadAllCommand = new RelayCommand(OnExecuteAssemblyReloadAll);
|
||||
@@ -113,6 +113,7 @@ namespace xunit.runner.wpf.ViewModel
|
||||
public ICommand WindowLoadedCommand { get; }
|
||||
public RelayCommand RunCommand { get; }
|
||||
public RelayCommand CancelCommand { get; }
|
||||
public ICommand TraitCheckedChangedCommand { get; }
|
||||
public ICommand TraitSelectionChangedCommand { get; }
|
||||
public ICommand TraitsClearCommand { get; }
|
||||
public ICommand AssemblyReloadCommand { get; }
|
||||
@@ -354,7 +355,7 @@ namespace xunit.runner.wpf.ViewModel
|
||||
this.traitCollectionView.Collection.Clear();
|
||||
foreach (var testCase in this.allTestCases)
|
||||
{
|
||||
this.traitCollectionView.Add(testCase.Traits);
|
||||
this.traitCollectionView.AddRange(testCase.Traits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,18 +477,18 @@ namespace xunit.runner.wpf.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTestDiscovered(List<TestCaseData> testCaseData)
|
||||
private void OnTestDiscovered(List<TestCaseData> testCaseDataList)
|
||||
{
|
||||
var allTraits = new SortedDictionary<string, SortedSet<string>>();
|
||||
foreach (var data in testCaseData)
|
||||
foreach (var data in testCaseDataList)
|
||||
{
|
||||
AddTraits(allTraits, data);
|
||||
}
|
||||
|
||||
this.allTestCases.AddRange(testCaseData.Select(d =>
|
||||
new TestCaseViewModel(d.DisplayName, d.AssemblyPath, Convert(CreateSortedTraits(d)).ToImmutableArray())));
|
||||
|
||||
this.traitCollectionView.Add(Convert(allTraits));
|
||||
this.allTestCases.AddRange(testCaseDataList.Select(d =>
|
||||
new TestCaseViewModel(d.DisplayName, d.AssemblyPath, Convert(CreateSortedTraits(d)))));
|
||||
|
||||
this.traitCollectionView.AddRange(Convert(allTraits));
|
||||
}
|
||||
|
||||
private SortedDictionary<string, SortedSet<string>> CreateSortedTraits(TestCaseData data)
|
||||
@@ -499,7 +500,16 @@ namespace xunit.runner.wpf.ViewModel
|
||||
|
||||
private static IEnumerable<TraitViewModel> Convert(SortedDictionary<string, SortedSet<string>> allTraits)
|
||||
{
|
||||
return allTraits.SelectMany(pair => pair.Value.Select(value => new TraitViewModel(pair.Key, value)));
|
||||
foreach (var trait in allTraits)
|
||||
{
|
||||
var name = trait.Key;
|
||||
var values = trait.Value;
|
||||
|
||||
var viewModel = new TraitViewModel(name);
|
||||
viewModel.AddValues(values);
|
||||
|
||||
yield return viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTraits(SortedDictionary<string, SortedSet<string>> allTraits, TestCaseData data)
|
||||
@@ -562,11 +572,9 @@ namespace xunit.runner.wpf.ViewModel
|
||||
this.cancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
private void OnExecuteTraitSelectionChanged()
|
||||
private void OnExecuteTraitCheckedChanged(TraitViewModel trait)
|
||||
{
|
||||
this.searchQuery.TraitSet = new HashSet<TraitViewModel>(
|
||||
this.traitCollectionView.Collection.Where(x => x.IsSelected),
|
||||
TraitViewModelComparer.Instance);
|
||||
this.searchQuery.TraitSet = this.traitCollectionView.GetCheckedTraits();
|
||||
FilterAfterDelay();
|
||||
}
|
||||
|
||||
@@ -574,7 +582,7 @@ namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
foreach (var cur in this.traitCollectionView.Collection)
|
||||
{
|
||||
cur.IsSelected = false;
|
||||
cur.IsChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
@@ -12,6 +8,6 @@ namespace xunit.runner.wpf.ViewModel
|
||||
public bool IncludePassedTests = true;
|
||||
public bool IncludeSkippedTests = true;
|
||||
public string SearchString = string.Empty;
|
||||
public HashSet<TraitViewModel> TraitSet = new HashSet<TraitViewModel>(TraitViewModelComparer.Instance);
|
||||
public ISet<TraitViewModel> TraitSet = new HashSet<TraitViewModel>(TraitViewModel.EqualityComparer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
using GalaSoft.MvvmLight;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using xunit.runner.data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
@@ -14,11 +9,11 @@ namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
private TestState _state = TestState.NotRun;
|
||||
|
||||
public TestCaseViewModel(string displayName, string assemblyFileName, ImmutableArray<TraitViewModel> traits)
|
||||
public TestCaseViewModel(string displayName, string assemblyFileName, IEnumerable<TraitViewModel> traits)
|
||||
{
|
||||
this.DisplayName = displayName;
|
||||
this.AssemblyFileName = assemblyFileName;
|
||||
this.Traits = traits;
|
||||
this.Traits = traits.ToImmutableArray();
|
||||
}
|
||||
|
||||
public string DisplayName { get; }
|
||||
|
||||
@@ -1,54 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
public sealed partial class TraitCollectionView
|
||||
{
|
||||
private readonly TraitViewModelComparer _comparer = TraitViewModelComparer.Instance;
|
||||
private readonly ObservableCollection<TraitViewModel> _collection = new ObservableCollection<TraitViewModel>();
|
||||
public ObservableCollection<TraitViewModel> Collection { get; } = new ObservableCollection<TraitViewModel>();
|
||||
|
||||
public ObservableCollection<TraitViewModel> Collection => _collection;
|
||||
|
||||
public TraitCollectionView()
|
||||
public void AddRange(IEnumerable<TraitViewModel> traits)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Add(IEnumerable<TraitViewModel> traitList)
|
||||
{
|
||||
foreach (var traitViewModel in traitList)
|
||||
foreach (var trait in traits)
|
||||
{
|
||||
InsertIfNotPresent(traitViewModel);
|
||||
var index = Collection.BinarySearch(trait, TraitViewModel.Comparer);
|
||||
if (index < 0)
|
||||
{
|
||||
Collection.Insert(~index, trait);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This trait already exists, add more values.
|
||||
var originalTrait = Collection[index];
|
||||
originalTrait.AddValues(trait.Children.Select(x => x.Text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertIfNotPresent(TraitViewModel trait)
|
||||
public ISet<TraitViewModel> GetCheckedTraits()
|
||||
{
|
||||
// TODO: make it a binary search
|
||||
for (int i = 0; i < _collection.Count; i++)
|
||||
{
|
||||
var current = _collection[i];
|
||||
var result = _comparer.Compare(trait, current);
|
||||
if (result < 0)
|
||||
{
|
||||
_collection.Insert(i, trait);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_collection.Add(trait);
|
||||
return new HashSet<TraitViewModel>(
|
||||
Collection.SelectMany(x => x.Children).Where(x => x.IsChecked == true),
|
||||
comparer: TraitViewModel.EqualityComparer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
public partial class TraitViewModel
|
||||
{
|
||||
private static readonly TraitViewModelComparer _comparer = new TraitViewModelComparer();
|
||||
|
||||
internal static IComparer<TraitViewModel> Comparer => _comparer;
|
||||
internal static IEqualityComparer<TraitViewModel> EqualityComparer => _comparer;
|
||||
|
||||
private class TraitViewModelComparer : IEqualityComparer<TraitViewModel>, IComparer<TraitViewModel>
|
||||
{
|
||||
public int Compare(TraitViewModel x, TraitViewModel y) => StringComparer.Ordinal.Compare(x.Text, y.Text);
|
||||
public bool Equals(TraitViewModel x, TraitViewModel y) => StringComparer.Ordinal.Equals(x.Text, y.Text);
|
||||
public int GetHashCode(TraitViewModel obj) => obj.Text.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,108 @@
|
||||
using GalaSoft.MvvmLight;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.ObjectModel;
|
||||
using GalaSoft.MvvmLight;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
public sealed class TraitViewModel : ViewModelBase
|
||||
public partial class TraitViewModel : ViewModelBase
|
||||
{
|
||||
private bool _isSelected;
|
||||
private readonly TraitViewModel _parent;
|
||||
private bool? _isChecked;
|
||||
private bool _isExpanded;
|
||||
private string _text;
|
||||
|
||||
public string Name { get; }
|
||||
public string Value { get; }
|
||||
public string DisplayName { get; }
|
||||
public ObservableCollection<TraitViewModel> Children { get; }
|
||||
|
||||
public bool IsSelected
|
||||
public TraitViewModel(string text)
|
||||
: this(null, text)
|
||||
{
|
||||
get { return _isSelected; }
|
||||
set { Set(ref _isSelected, value); }
|
||||
}
|
||||
|
||||
public TraitViewModel(string name, string value)
|
||||
private TraitViewModel(TraitViewModel parent, string text)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
DisplayName = $"{Name}={Value}";
|
||||
this._parent = parent;
|
||||
this._isChecked = false;
|
||||
this._isExpanded = true;
|
||||
this._text = text;
|
||||
this.Children = new ObservableCollection<TraitViewModel>();
|
||||
}
|
||||
|
||||
private void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
|
||||
{
|
||||
if (value == this._isChecked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._isChecked = value;
|
||||
|
||||
if (updateChildren && value != null)
|
||||
{
|
||||
foreach (var child in this.Children)
|
||||
{
|
||||
child.SetIsChecked(value, updateChildren: true, updateParent: false);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateParent && _parent != null)
|
||||
{
|
||||
_parent.VerifyCheckState();
|
||||
}
|
||||
|
||||
this.RaisePropertyChanged(nameof(IsChecked));
|
||||
}
|
||||
|
||||
private void VerifyCheckState()
|
||||
{
|
||||
bool? state = null;
|
||||
var isFirst = true;
|
||||
|
||||
foreach (var child in this.Children)
|
||||
{
|
||||
if (isFirst)
|
||||
{
|
||||
state = child.IsChecked;
|
||||
isFirst = false;
|
||||
}
|
||||
else if (state != child.IsChecked)
|
||||
{
|
||||
state = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.SetIsChecked(state, updateChildren: false, updateParent: true);
|
||||
}
|
||||
|
||||
public void AddValues(IEnumerable<string> values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
var index = this.Children.BinarySearch(value, StringComparer.Ordinal.Compare, v => v.Text);
|
||||
if (index < 0)
|
||||
{
|
||||
this.Children.Insert(~index, new TraitViewModel(this, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsChecked
|
||||
{
|
||||
get { return _isChecked; }
|
||||
set { SetIsChecked(value, updateChildren: true, updateParent: true); }
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get { return _isExpanded; }
|
||||
set { Set(ref _isExpanded, value); }
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return _text; }
|
||||
set { Set(ref _text, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace xunit.runner.wpf.ViewModel
|
||||
{
|
||||
internal sealed class TraitViewModelComparer : IEqualityComparer<TraitViewModel>, IComparer<TraitViewModel>
|
||||
{
|
||||
internal static readonly TraitViewModelComparer Instance = new TraitViewModelComparer();
|
||||
|
||||
private readonly StringComparer _comparer = StringComparer.Ordinal;
|
||||
|
||||
public int Compare(TraitViewModel x, TraitViewModel y)
|
||||
{
|
||||
var result = _comparer.Compare(x.Name, y.Name);
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return _comparer.Compare(x.Value, y.Value);
|
||||
}
|
||||
|
||||
public bool Equals(TraitViewModel x, TraitViewModel y)
|
||||
{
|
||||
return _comparer.Equals(x.Name, y.Name)
|
||||
&& _comparer.Equals(x.Value, y.Value);
|
||||
}
|
||||
|
||||
public int GetHashCode(TraitViewModel obj)
|
||||
{
|
||||
return obj.Name.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,14 +102,15 @@
|
||||
</Compile>
|
||||
<Compile Include="Storage.cs" />
|
||||
<Compile Include="Storage.WindowPlacement.cs" />
|
||||
<Compile Include="Extensions.FuncComparer.cs" />
|
||||
<Compile Include="ViewModel\TraitCollectionView.cs" />
|
||||
<Compile Include="ViewModel\AssemblyAndConfigFile.cs" />
|
||||
<Compile Include="ViewModel\MainViewModel.cs" />
|
||||
<Compile Include="ViewModel\SearchQuery.cs" />
|
||||
<Compile Include="ViewModel\TestCaseViewModel.cs" />
|
||||
<Compile Include="ViewModel\TestAssemblyViewModel.cs" />
|
||||
<Compile Include="ViewModel\TraitViewModel.Comparer.cs" />
|
||||
<Compile Include="ViewModel\TraitViewModel.cs" />
|
||||
<Compile Include="ViewModel\TraitViewModelComparer.cs" />
|
||||
<Compile Include="ViewModel\ViewModelLocator.cs" />
|
||||
<Page Include="LoadingDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
|
||||
Reference in New Issue
Block a user