diff --git a/.gitignore b/.gitignore
index a3a8ec3..e8fcf3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,3 +106,5 @@ $RECYCLE.BIN/
# ide temp
*.sln.ide/
+/.vs
+/src/.vs/AutoMerge/v15/Server/sqlite3
diff --git a/src/AutoMerge.Tests/AutoMerge.Tests.csproj b/src/AutoMerge.Tests/AutoMerge.Tests.csproj
index 8869404..e1b7b79 100644
--- a/src/AutoMerge.Tests/AutoMerge.Tests.csproj
+++ b/src/AutoMerge.Tests/AutoMerge.Tests.csproj
@@ -14,6 +14,7 @@
v4.6.2
512
ea07ad34
+
true
@@ -70,6 +71,9 @@
AutoMerge
+
+
+
diff --git a/src/AutoMerge/AutoMerge.csproj b/src/AutoMerge/AutoMerge.csproj
index af59e48..11c43e0 100644
--- a/src/AutoMerge/AutoMerge.csproj
+++ b/src/AutoMerge/AutoMerge.csproj
@@ -1,424 +1,448 @@
-
+
-
- $(VisualStudioVersion)
- 12.0
- $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
- Program
- $(DevEnvDir)\devenv.exe
- /rootsuffix Exp
-
-
-
-
- Debug
- AnyCPU
- 2.0
- {726ED85E-2274-4D95-B822-B2CFE2CE44B9}
- {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Library
- Properties
- AutoMerge
- AutoMerge
- True
- Key.snk
- v4.5
- v4.6.2
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- true
-
-
-
-
- ..\..\lib\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\Microsoft.Expression.Interactions.dll
- True
-
-
- False
-
-
- False
-
-
- False
-
-
- False
-
-
- False
-
-
- true
-
-
- true
-
-
- False
-
-
- False
-
-
- False
-
-
- False
-
-
- False
-
-
-
-
-
-
-
-
-
-
-
-
- ..\..\lib\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\System.Windows.Interactivity.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
+
+ $(VisualStudioVersion)
+ 12.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ Program
+ $(DevEnvDir)\devenv.exe
+ /rootsuffix Exp
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {726ED85E-2274-4D95-B822-B2CFE2CE44B9}
+ {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ AutoMerge
+ AutoMerge
+ True
+ Key.snk
+ v4.5
+ v4.6.2
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+ ..\..\lib\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\Microsoft.Expression.Interactions.dll
+ True
-
- False
+
+ False
-
- False
+
+ False
-
- False
+
+ False
-
- False
+
+ False
-
- False
+
+ False
-
-
-
-
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Client.dll
- False
+
+ true
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Common.dll
- False
+
+ true
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Controls.dll
- False
+
+ False
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.VersionControl.Client.dll
- False
+
+ False
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.VersionControl.Common.dll
- False
+
+ False
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
- False
+
+ False
-
-
-
-
-
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Client.dll
- False
+
+ False
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Common.dll
- False
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\lib\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\System.Windows.Interactivity.dll
+ True
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Controls.dll
- False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Client.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Common.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.Controls.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\14.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ False
+
+
+
+
+
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Client.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Common.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Controls.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.VersionControl.Client.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.VersionControl.Common.dll
+ False
+
+
+ C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
+ False
+
+
+
+
+
+
+ True
+ ..\..\lib\EnvDTE.8.0.1\lib\net10\EnvDTE.dll
+ True
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.VersionControl.Client.dll
- False
+
+ True
+ ..\..\lib\EnvDTE100.10.0.1\lib\net20\EnvDTE100.dll
+ True
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.VersionControl.Common.dll
- False
+
+ True
+ ..\..\lib\EnvDTE80.8.0.1\lib\net10\EnvDTE80.dll
+ True
-
- C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.WorkItemTracking.Client.dll
- False
+
+ True
+ ..\..\lib\EnvDTE90.9.0.1\lib\net10\EnvDTE90.dll
+ True
-
-
-
-
-
- True
- ..\..\lib\EnvDTE.8.0.1\lib\net10\EnvDTE.dll
- True
-
-
- True
- ..\..\lib\EnvDTE100.10.0.1\lib\net20\EnvDTE100.dll
- True
-
-
- True
- ..\..\lib\EnvDTE80.8.0.1\lib\net10\EnvDTE80.dll
- True
-
-
- True
- ..\..\lib\EnvDTE90.9.0.1\lib\net10\EnvDTE90.dll
- True
-
-
- True
- ..\..\lib\EnvDTE90a.9.0.1\lib\net10\EnvDTE90a.dll
- True
-
-
- {1CBA492E-7263-47BB-87FE-639000619B15}
- 8
- 0
- 0
- primary
- False
- False
-
-
- {00020430-0000-0000-C000-000000000046}
- 2
- 0
- 0
- primary
- False
- False
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BranchesView.xaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SplitButton.xaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- RecentChangesetsView.xaml
-
-
-
-
- True
- True
- Resources.resx
-
-
-
-
-
-
-
-
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
- Designer
-
-
- true
- VSPackage
-
-
-
-
-
-
-
- LICENSE.txt
- true
-
-
- RELEASE_NOTES.md
- true
-
-
- Always
- true
-
-
-
- Always
- true
-
-
-
-
-
- Designer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
- MSBuild:Compile
-
-
- Designer
- MSBuild:Compile
-
-
- Designer
- MSBuild:Compile
-
-
- Designer
- MSBuild:Compile
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/AutoMerge/AutoMergeTeamNavigationItem.cs b/src/AutoMerge/AutoMergeTeamNavigationItem.cs
new file mode 100644
index 0000000..953d60d
--- /dev/null
+++ b/src/AutoMerge/AutoMergeTeamNavigationItem.cs
@@ -0,0 +1,23 @@
+using System;
+using System.ComponentModel.Composition;
+using AutoMerge.Base;
+using AutoMerge.VersionControl;
+using Microsoft.TeamFoundation.Controls;
+using Microsoft.VisualStudio.Shell;
+
+namespace AutoMerge
+{
+ [TeamExplorerNavigationItem(GuidList.AutoMergeTeamNavigationItemId, 211, TargetPageId = GuidList.AutoMergeTeamPageId)]
+ class AutoMergeTeamNavigationItem : TeamExplorerNavigationItemBase
+ {
+ [ImportingConstructor]
+ public AutoMergeTeamNavigationItem(
+ [Import(typeof(SVsServiceProvider))]
+ IServiceProvider serviceProvider)
+ : base(serviceProvider, GuidList.AutoMergeTeamPageId, VersionControlProvider.TeamFoundation)
+ {
+ Text = Resources.AutoMergeTeamPageName;
+ Image = Resources.MergeImage;
+ }
+ }
+}
diff --git a/src/AutoMerge/AutoMergeTeamPage.cs b/src/AutoMerge/AutoMergeTeamPage.cs
new file mode 100644
index 0000000..1e70b1f
--- /dev/null
+++ b/src/AutoMerge/AutoMergeTeamPage.cs
@@ -0,0 +1,14 @@
+using AutoMerge.Base;
+using Microsoft.TeamFoundation.Controls;
+
+namespace AutoMerge
+{
+ [TeamExplorerPage(GuidList.AutoMergeTeamPageId)]
+ public class AutoMergeTeamPage : TeamExplorerPageBase
+ {
+ public AutoMergeTeamPage()
+ {
+ Title = Resources.AutoMergeTeamPageName;
+ }
+ }
+}
diff --git a/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs b/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
index 5bfb91e..736c256 100644
--- a/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
+++ b/src/AutoMerge/Base/TeamExplorerSectionViewModelBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common.Internal;
@@ -33,11 +33,9 @@ protected virtual Task InitializeAsync(object sender, SectionInitializeEventArgs
return _emptyTask;
}
- public async override void Initialize(object sender, SectionInitializeEventArgs e)
+ public override async void Initialize(object sender, SectionInitializeEventArgs e)
{
- ShowBusy();
-
- try
+ await SetBusyWhileExecutingAsync(async () =>
{
base.Initialize(sender, e);
if (ServiceProvider != null)
@@ -52,22 +50,24 @@ public async override void Initialize(object sender, SectionInitializeEventArgs
}
}
await InitializeAsync(sender, e);
- }
- catch (Exception ex)
- {
- ShowError(ex.Message);
- }
+ });
+ }
- HideBusy();
+ public override async void Refresh()
+ {
+ await SetBusyWhileExecutingAsync(async () =>
+ {
+ await RefreshAsync();
+ });
}
- public async override void Refresh()
+ protected async Task SetBusyWhileExecutingAsync(Func task)
{
ShowBusy();
try
{
- await RefreshAsync();
+ await task();
}
catch (Exception ex)
{
diff --git a/src/AutoMerge/Branches/Branch.cs b/src/AutoMerge/Branches/Branch.cs
new file mode 100644
index 0000000..5b536ee
--- /dev/null
+++ b/src/AutoMerge/Branches/Branch.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace AutoMerge.Branches
+{
+ public class Branch
+ {
+ public string Name { get; set; }
+
+ public List Branches { get; set; }
+ }
+}
diff --git a/src/AutoMerge/Branches/BranchesViewModel.cs b/src/AutoMerge/Branches/BranchesViewModel.cs
index a80d6d5..8b12fde 100644
--- a/src/AutoMerge/Branches/BranchesViewModel.cs
+++ b/src/AutoMerge/Branches/BranchesViewModel.cs
@@ -177,16 +177,6 @@ public ObservableCollection MergeModes
public DelegateCommand OpenSourceControlExplorerCommand { get; set; }
- private static ObservableCollection GetWorkspaces(VersionControlServer versionControl, TfsTeamProjectCollection tfs)
- {
- var queryWorkspaces = versionControl.QueryWorkspaces(null, tfs.AuthorizedIdentity.UniqueName, Environment.MachineName);
- if (queryWorkspaces.Length > 1)
- {
- return new ObservableCollection(queryWorkspaces.OrderBy(w => w.Name));
- }
- return new ObservableCollection(queryWorkspaces);
- }
-
protected async override Task InitializeAsync(object sender, SectionInitializeEventArgs e)
{
Logger.Debug("Start initilize branches section");
@@ -204,7 +194,7 @@ protected async override Task InitializeAsync(object sender, SectionInitializeEv
if (e.Context == null)
{
- Workspaces = GetWorkspaces(versionControl, tfs);
+ Workspaces = WorkspaceHelper.GetWorkspaces(versionControl, tfs);
if (Workspaces.Count > 0)
{
Workspace = WorkspaceHelper.GetWorkspace(versionControl, Workspaces);
@@ -1252,7 +1242,7 @@ private void RefreshWorkspaces(object sender, WorkspaceEventArgs e)
var tfs = Context.TeamProjectCollection;
var versionControl = tfs.GetService();
- Workspaces = GetWorkspaces(versionControl, tfs);
+ Workspaces = WorkspaceHelper.GetWorkspaces(versionControl, tfs);
if (Workspaces.Count > 0)
{
Workspace = Workspaces[0];
diff --git a/src/AutoMerge/RecentChangesets/ChangesetCommentConverter.cs b/src/AutoMerge/Changesets/ChangesetCommentConverter.cs
similarity index 100%
rename from src/AutoMerge/RecentChangesets/ChangesetCommentConverter.cs
rename to src/AutoMerge/Changesets/ChangesetCommentConverter.cs
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetFocusableControlNames.cs b/src/AutoMerge/Changesets/ChangesetFocusableControlNames.cs
similarity index 72%
rename from src/AutoMerge/RecentChangesets/RecentChangesetFocusableControlNames.cs
rename to src/AutoMerge/Changesets/ChangesetFocusableControlNames.cs
index 2f9b966..e445736 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetFocusableControlNames.cs
+++ b/src/AutoMerge/Changesets/ChangesetFocusableControlNames.cs
@@ -1,9 +1,9 @@
-namespace AutoMerge
+namespace AutoMerge
{
- public class RecentChangesetFocusableControlNames
+ public class ChangesetFocusableControlNames
{
public const string ChangesetIdTextBox = "changesetIdTextBox";
public const string AddChangesetByIdLink = "addChangesetByIdLink";
public const string ChangesetList = "changesetList";
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoMerge/RecentChangesets/ChangesetViewModel.cs b/src/AutoMerge/Changesets/ChangesetViewModel.cs
similarity index 100%
rename from src/AutoMerge/RecentChangesets/ChangesetViewModel.cs
rename to src/AutoMerge/Changesets/ChangesetViewModel.cs
diff --git a/src/AutoMerge/Changesets/ChangesetsViewModel.cs b/src/AutoMerge/Changesets/ChangesetsViewModel.cs
new file mode 100644
index 0000000..143e2b2
--- /dev/null
+++ b/src/AutoMerge/Changesets/ChangesetsViewModel.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using AutoMerge.Events;
+using AutoMerge.Prism.Command;
+using AutoMerge.Prism.Events;
+using Microsoft.TeamFoundation;
+using Microsoft.TeamFoundation.Client;
+using Microsoft.TeamFoundation.Controls;
+using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer;
+using Task = System.Threading.Tasks.Task;
+
+using TeamExplorerSectionViewModelBase = AutoMerge.Base.TeamExplorerSectionViewModelBase;
+
+namespace AutoMerge
+{
+ public abstract class ChangesetsViewModel : TeamExplorerSectionViewModelBase
+ {
+ private readonly IEventAggregator _eventAggregator;
+
+ protected ChangesetsViewModel(ILogger logger)
+ : base(logger)
+ {
+ Title = BaseTitle;
+ IsVisible = true;
+ IsExpanded = true;
+ IsBusy = false;
+ Changesets = new ObservableCollection();
+
+ _eventAggregator = EventAggregatorFactory.Get();
+ _eventAggregator.GetEvent()
+ .Subscribe(OnMergeComplete);
+
+ ViewChangesetDetailsCommand = new DelegateCommand(ViewChangesetDetailsExecute, ViewChangesetDetailsCanExecute);
+ }
+
+ public ChangesetViewModel SelectedChangeset
+ {
+ get
+ {
+ return _selectedChangeset;
+ }
+ set
+ {
+ _selectedChangeset = value;
+ RaisePropertyChanged("SelectedChangeset");
+ _eventAggregator.GetEvent().Publish(value);
+ }
+ }
+ private ChangesetViewModel _selectedChangeset;
+
+ public ObservableCollection Changesets
+ {
+ get
+ {
+ return _changesets;
+ }
+ protected set
+ {
+ _changesets = value;
+ RaisePropertyChanged("Changesets");
+ }
+ }
+ private ObservableCollection _changesets;
+
+
+
+ public DelegateCommand ViewChangesetDetailsCommand { get; private set; }
+
+ private void ViewChangesetDetailsExecute()
+ {
+ var changesetId = SelectedChangeset.ChangesetId;
+ TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
+ }
+
+ private bool ViewChangesetDetailsCanExecute()
+ {
+ return SelectedChangeset != null;
+ }
+
+ private async void OnMergeComplete(bool obj)
+ {
+ await RefreshAsync();
+ }
+
+ protected override async Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ {
+ if (e.Context == null)
+ {
+ await RefreshAsync();
+ }
+ else
+ {
+ RestoreContext(e);
+ }
+ }
+
+ protected async Task GetChangesetAndUpdateTitleAsync()
+ {
+ Changesets.Clear();
+
+ Logger.Info("Getting changesets ...");
+ var changesets = await GetChangesetsAsync();
+ Logger.Info("Getting changesets end");
+
+ Changesets = new ObservableCollection(changesets);
+ UpdateTitle();
+
+ if (Changesets.Count > 0)
+ {
+ if (SelectedChangeset == null || SelectedChangeset.ChangesetId != Changesets[0].ChangesetId)
+ SelectedChangeset = Changesets[0];
+ }
+ }
+
+ public abstract Task> GetChangesetsAsync();
+
+ protected void UpdateTitle()
+ {
+ Title = Changesets.Count > 0
+ ? string.Format("{0} ({1})", BaseTitle, Changesets.Count)
+ : BaseTitle;
+ }
+
+ protected virtual void InvalidateCommands()
+ {
+ ViewChangesetDetailsCommand.RaiseCanExecuteChanged();
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ _eventAggregator.GetEvent().Unsubscribe(OnMergeComplete);
+ }
+
+ protected abstract void RestoreContext(SectionInitializeEventArgs e);
+
+ protected override void OnContextChanged(object sender, ContextChangedEventArgs e)
+ {
+ Refresh();
+ }
+
+ protected abstract string BaseTitle { get; }
+ }
+}
diff --git a/src/AutoMerge/Changesets/ChangesetsViewModelContext.cs b/src/AutoMerge/Changesets/ChangesetsViewModelContext.cs
new file mode 100644
index 0000000..1b4fe88
--- /dev/null
+++ b/src/AutoMerge/Changesets/ChangesetsViewModelContext.cs
@@ -0,0 +1,14 @@
+using System.Collections.ObjectModel;
+
+namespace AutoMerge
+{
+ public class ChangesetsViewModelContext
+ {
+ public ObservableCollection Changesets { get; set; }
+
+ public string Title { get; set; }
+
+ public ChangesetViewModel SelectedChangeset { get; set; }
+ }
+
+}
diff --git a/src/AutoMerge/Changesets/Providers/ChangesetByIdChangesetProvider.cs b/src/AutoMerge/Changesets/Providers/ChangesetByIdChangesetProvider.cs
new file mode 100644
index 0000000..2d38b38
--- /dev/null
+++ b/src/AutoMerge/Changesets/Providers/ChangesetByIdChangesetProvider.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AutoMerge
+{
+ public class ChangesetByIdChangesetProvider : ChangesetProviderBase
+ {
+ private readonly IEnumerable _changesetIds;
+
+ public ChangesetByIdChangesetProvider(IServiceProvider serviceProvider, IEnumerable changesetIds)
+ : base(serviceProvider)
+ {
+ if (changesetIds == null)
+ throw new ArgumentNullException("changesetIds");
+
+ _changesetIds = changesetIds;
+ }
+
+ protected override List GetChangesetsInternal()
+ {
+ var changesets = new List();
+ var changesetService = GetChangesetService();
+ if (changesetService != null)
+ {
+ changesets = _changesetIds
+ .Select(changesetService.GetChangeset)
+ .Where(c => c != null)
+ .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
+ .ToList();
+ }
+
+ return changesets;
+ }
+ }
+}
diff --git a/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs b/src/AutoMerge/Changesets/Providers/ChangesetProviderBase.cs
similarity index 79%
rename from src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs
rename to src/AutoMerge/Changesets/Providers/ChangesetProviderBase.cs
index 17627e5..fc8446c 100644
--- a/src/AutoMerge/RecentChangesets/ChangesetProviderBase.cs
+++ b/src/AutoMerge/Changesets/Providers/ChangesetProviderBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -17,12 +17,12 @@ protected ChangesetProviderBase(IServiceProvider serviceProvider)
_changesetService = new Lazy(InitChangesetService);
}
- public Task> GetChangesets(string userLogin)
+ public Task> GetChangesets()
{
- return Task.Run(() => GetChangesetsInternal(userLogin));
+ return Task.Run(() => GetChangesetsInternal());
}
- protected abstract List GetChangesetsInternal(string userLogin);
+ protected abstract List GetChangesetsInternal();
protected ChangesetViewModel ToChangesetViewModel(Changeset tfsChangeset, ChangesetService changesetService)
{
@@ -57,14 +57,9 @@ private ChangesetService InitChangesetService()
return null;
}
- protected string GetProjectName()
- {
- var context = VersionControlNavigationHelper.GetTeamFoundationContext(_serviceProvider);
- if (context != null)
- {
- return context.TeamProjectName;
- }
- return null;
+ protected IServiceProvider ServiceProvider()
+ {
+ return _serviceProvider;
}
}
}
diff --git a/src/AutoMerge/Changesets/Providers/IChangesetProvider.cs b/src/AutoMerge/Changesets/Providers/IChangesetProvider.cs
new file mode 100644
index 0000000..e41a9c5
--- /dev/null
+++ b/src/AutoMerge/Changesets/Providers/IChangesetProvider.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace AutoMerge
+{
+ public interface IChangesetProvider
+ {
+ Task> GetChangesets();
+ }
+}
diff --git a/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs b/src/AutoMerge/Changesets/Providers/MyChangesetChangesetProvider.cs
similarity index 71%
rename from src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs
rename to src/AutoMerge/Changesets/Providers/MyChangesetChangesetProvider.cs
index 733d923..ea3b9b1 100644
--- a/src/AutoMerge/RecentChangesets/MyChangesetChangesetProvider.cs
+++ b/src/AutoMerge/Changesets/Providers/MyChangesetChangesetProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,25 +7,27 @@ namespace AutoMerge
public class MyChangesetChangesetProvider : ChangesetProviderBase
{
private readonly int _maxChangesetCount;
+ private readonly string _userLogin;
- public MyChangesetChangesetProvider(IServiceProvider serviceProvider, int maxChangesetCount)
+ public MyChangesetChangesetProvider(IServiceProvider serviceProvider, int maxChangesetCount, string userLogin)
: base(serviceProvider)
{
_maxChangesetCount = maxChangesetCount;
+ _userLogin = userLogin;
}
- protected override List GetChangesetsInternal(string userLogin)
+ protected override List GetChangesetsInternal()
{
var changesets = new List();
- if (!string.IsNullOrEmpty(userLogin))
+ if (!string.IsNullOrEmpty(_userLogin))
{
var changesetService = GetChangesetService();
if (changesetService != null)
{
- var projectName = GetProjectName();
- var tfsChangesets = changesetService.GetUserChangesets(projectName, userLogin, _maxChangesetCount);
+ var projectName = ProjectNameHelper.GetProjectName(ServiceProvider());
+ var tfsChangesets = changesetService.GetUserChangesets(projectName, _userLogin, _maxChangesetCount);
changesets = tfsChangesets
.Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
.ToList();
diff --git a/src/AutoMerge/Changesets/Providers/TeamChangesetChangesetProvider.cs b/src/AutoMerge/Changesets/Providers/TeamChangesetChangesetProvider.cs
new file mode 100644
index 0000000..c896de4
--- /dev/null
+++ b/src/AutoMerge/Changesets/Providers/TeamChangesetChangesetProvider.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AutoMerge.Branches;
+using Microsoft.TeamFoundation.VersionControl.Client;
+
+
+namespace AutoMerge
+{
+ public class TeamChangesetChangesetProvider : ChangesetProviderBase
+ {
+ private string _sourceBranch;
+ private string _targetBranch;
+
+
+ public TeamChangesetChangesetProvider(IServiceProvider serviceProvider) : base(serviceProvider)
+ {
+ }
+
+ public List ListProjects()
+ {
+ List result = new List();
+
+ var changesetService = GetChangesetService();
+
+ if (changesetService != null)
+ {
+ result.AddRange(changesetService.ListTfsProjects());
+ }
+
+ return result;
+ }
+
+ public List ListBranches(string projectName)
+ {
+ var result = new List();
+
+ var changesetService = GetChangesetService();
+
+ if (changesetService != null)
+ {
+ var branches = changesetService.ListBranches(projectName);
+
+ foreach (var branchObject in branches)
+ {
+ var branch = new Branch();
+
+ branch.Name = branchObject.Properties.RootItem.Item;
+ branch.Branches = branchObject.ChildBranches.Where(x => !x.IsDeleted).Select(x => x.Item).ToList();
+
+ if (branchObject.Properties.ParentBranch != null)
+ {
+ branch.Branches.Add(branchObject.Properties.ParentBranch.Item);
+ }
+
+ result.Add(branch);
+ }
+ }
+
+ return result;
+
+ }
+
+ public void SetSourceAndTargetBranch(string sourceBranch, string targetBranch)
+ {
+ _sourceBranch = sourceBranch;
+ _targetBranch = targetBranch;
+ }
+
+ protected override List GetChangesetsInternal()
+ {
+ var changesets = new List();
+
+ var changesetService = GetChangesetService();
+
+ if (changesetService != null)
+ {
+ var tfsChangesets = changesetService.GetMergeCandidates(_sourceBranch, _targetBranch);
+
+ changesets = tfsChangesets
+ .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
+ .ToList();
+ }
+
+ return changesets;
+ }
+
+ }
+}
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsSection.cs b/src/AutoMerge/Changesets/RecentChangesetsSection.cs
similarity index 75%
rename from src/AutoMerge/RecentChangesets/RecentChangesetsSection.cs
rename to src/AutoMerge/Changesets/RecentChangesetsSection.cs
index 77b2d79..f0a6c58 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsSection.cs
+++ b/src/AutoMerge/Changesets/RecentChangesetsSection.cs
@@ -1,4 +1,5 @@
-using AutoMerge.Base;
+using AutoMerge.Base;
+using AutoMerge.RecentChangesets.Solo;
using Microsoft.TeamFoundation.Controls;
namespace AutoMerge
@@ -8,14 +9,14 @@ public class RecentChangesetsSection : TeamExplorerSectionBase
{
protected override ITeamExplorerSection CreateViewModel(SectionInitializeEventArgs e)
{
- var viewModel = base.CreateViewModel(e) ?? new RecentChangesetsViewModel(new VsLogger(ServiceProvider));
+ var viewModel = base.CreateViewModel(e) ?? new RecentChangesetsSoloViewModel(new VsLogger(ServiceProvider));
return viewModel;
}
protected override object CreateView(SectionInitializeEventArgs e)
{
- return new RecentChangesetsView();
+ return new RecentChangesetsSoloView();
}
}
}
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml
similarity index 71%
rename from src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml
rename to src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml
index 93a6afc..d4694b4 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml
+++ b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml
@@ -1,4 +1,4 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml.cs b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml.cs
similarity index 70%
rename from src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml.cs
rename to src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml.cs
index 4fe095b..80ef617 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsView.xaml.cs
+++ b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloView.xaml.cs
@@ -1,4 +1,4 @@
-using System.Windows.Controls;
+using System.Windows.Controls;
using Microsoft.TeamFoundation.Controls.MVVM;
namespace AutoMerge
@@ -6,9 +6,9 @@ namespace AutoMerge
///
/// Interaction logic for RecentChangesetsView.xaml
///
- public partial class RecentChangesetsView : UserControl, IFocusService
+ public partial class RecentChangesetsSoloView : UserControl, IFocusService
{
- public RecentChangesetsView()
+ public RecentChangesetsSoloView()
{
InitializeComponent();
}
@@ -17,14 +17,14 @@ public void SetFocus(string id, params object[] args)
{
switch (id)
{
- case RecentChangesetFocusableControlNames.AddChangesetByIdLink:
+ case ChangesetFocusableControlNames.AddChangesetByIdLink:
addChangesetByIdLink.Focus();
break;
- case RecentChangesetFocusableControlNames.ChangesetIdTextBox:
+ case ChangesetFocusableControlNames.ChangesetIdTextBox:
changesetIdTextBox.FocusTextBox();
changesetIdTextBox.TextBoxControl.SelectionStart = changesetIdTextBox.TextBoxControl.Text.Length;
break;
- case RecentChangesetFocusableControlNames.ChangesetList:
+ case ChangesetFocusableControlNames.ChangesetList:
if (changesetList.SelectedItem != null)
{
changesetList.UpdateLayout();
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModel.cs
similarity index 54%
rename from src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs
rename to src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModel.cs
index c5c5567..e1b5d8b 100644
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModel.cs
+++ b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModel.cs
@@ -1,72 +1,24 @@
-using System;
+using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using AutoMerge.Events;
+using System.Threading.Tasks;
using AutoMerge.Prism.Command;
-using AutoMerge.Prism.Events;
using Microsoft.TeamFoundation;
-using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Controls;
-using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer;
-using Task = System.Threading.Tasks.Task;
-using TeamExplorerSectionViewModelBase = AutoMerge.Base.TeamExplorerSectionViewModelBase;
-
-namespace AutoMerge
+namespace AutoMerge.RecentChangesets.Solo
{
- public sealed class RecentChangesetsViewModel : TeamExplorerSectionViewModelBase
+ public class RecentChangesetsSoloViewModel : ChangesetsViewModel
{
- private readonly string _baseTitle;
- private readonly IEventAggregator _eventAggregator;
-
- public RecentChangesetsViewModel(ILogger logger)
- : base(logger)
+ public RecentChangesetsSoloViewModel(ILogger logger) : base(logger)
{
- Title = Resources.RecentChangesetSectionName;
- IsVisible = true;
- IsExpanded = true;
- IsBusy = false;
- Changesets = new ObservableCollection();
- _baseTitle = Title;
-
- _eventAggregator = EventAggregatorFactory.Get();
- _eventAggregator.GetEvent()
- .Subscribe(OnMergeComplete);
-
- ViewChangesetDetailsCommand = new DelegateCommand(ViewChangesetDetailsExecute, ViewChangesetDetailsCanExecute);
ToggleAddByIdCommand = new DelegateCommand(ToggleAddByIdExecute, ToggleAddByIdCanExecute);
CancelAddChangesetByIdCommand = new DelegateCommand(CancelAddByIdExecute);
AddChangesetByIdCommand = new DelegateCommand(AddChangesetByIdExecute, AddChangesetByIdCanExecute);
}
- public ChangesetViewModel SelectedChangeset
- {
- get
- {
- return _selectedChangeset;
- }
- set
- {
- _selectedChangeset = value;
- RaisePropertyChanged("SelectedChangeset");
- _eventAggregator.GetEvent().Publish(value);
- }
- }
- private ChangesetViewModel _selectedChangeset;
-
- public ObservableCollection Changesets
- {
- get
- {
- return _changesets;
- }
- private set
- {
- _changesets = value;
- RaisePropertyChanged("Changesets");
- }
- }
- private ObservableCollection _changesets;
+ public DelegateCommand ToggleAddByIdCommand { get; private set; }
+ public DelegateCommand CancelAddChangesetByIdCommand { get; private set; }
+ public DelegateCommand AddChangesetByIdCommand { get; private set; }
public bool ShowAddByIdChangeset
{
@@ -97,68 +49,12 @@ public string ChangesetIdsText
}
private string _changesetIdsText;
- public DelegateCommand ViewChangesetDetailsCommand { get; private set; }
-
- public DelegateCommand ToggleAddByIdCommand { get; private set; }
-
- public DelegateCommand AddChangesetByIdCommand { get; private set; }
-
- public DelegateCommand CancelAddChangesetByIdCommand { get; private set; }
-
- private void ViewChangesetDetailsExecute()
- {
- var changesetId = SelectedChangeset.ChangesetId;
- TeamExplorerUtils.Instance.NavigateToPage(TeamExplorerPageIds.ChangesetDetails, ServiceProvider, changesetId);
- }
-
- private bool ViewChangesetDetailsCanExecute()
- {
- return SelectedChangeset != null;
- }
-
- private async void OnMergeComplete(bool obj)
- {
- await RefreshAsync();
- }
-
- protected override async Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ public override async Task> GetChangesetsAsync()
{
- if (e.Context == null)
- {
- await RefreshAsync();
- }
- else
- {
- RestoreContext(e);
- }
- }
-
- protected override async Task RefreshAsync()
- {
- Changesets.Clear();
-
- var changesetProvider = new MyChangesetChangesetProvider(ServiceProvider, Settings.Instance.ChangesetCount);
var userLogin = VersionControlNavigationHelper.GetAuthorizedUser(ServiceProvider);
+ var changesetProvider = new MyChangesetChangesetProvider(ServiceProvider, Settings.Instance.ChangesetCount, userLogin);
- Logger.Info("Getting changesets ...");
- var changesets = await changesetProvider.GetChangesets(userLogin);
- Logger.Info("Getting changesets end");
-
- Changesets = new ObservableCollection(changesets);
- UpdateTitle();
-
- if (Changesets.Count > 0)
- {
- if (SelectedChangeset == null || SelectedChangeset.ChangesetId != Changesets[0].ChangesetId)
- SelectedChangeset = Changesets[0];
- }
- }
-
- private void UpdateTitle()
- {
- Title = Changesets.Count > 0
- ? string.Format("{0} ({1})", _baseTitle, Changesets.Count)
- : _baseTitle;
+ return await changesetProvider.GetChangesets();
}
private void ToggleAddByIdExecute()
@@ -168,7 +64,7 @@ private void ToggleAddByIdExecute()
ShowAddByIdChangeset = true;
InvalidateCommands();
ResetAddById();
- SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetIdTextBox);
+ SetMvvmFocus(ChangesetFocusableControlNames.ChangesetIdTextBox);
}
catch (Exception ex)
{
@@ -188,7 +84,7 @@ private void CancelAddByIdExecute()
{
ShowAddByIdChangeset = false;
InvalidateCommands();
- SetMvvmFocus(RecentChangesetFocusableControlNames.AddChangesetByIdLink);
+ SetMvvmFocus(ChangesetFocusableControlNames.AddChangesetByIdLink);
ResetAddById();
}
catch (Exception ex)
@@ -202,6 +98,11 @@ private void ResetAddById()
ChangesetIdsText = string.Empty;
}
+ protected override async Task RefreshAsync()
+ {
+ await GetChangesetAndUpdateTitleAsync();
+ }
+
private async void AddChangesetByIdExecute()
{
ShowBusy();
@@ -211,13 +112,13 @@ private async void AddChangesetByIdExecute()
if (changesetIds.Count > 0)
{
var changesetProvider = new ChangesetByIdChangesetProvider(ServiceProvider, changesetIds);
- var changesets = await changesetProvider.GetChangesets(null);
+ var changesets = await changesetProvider.GetChangesets();
if (changesets.Count > 0)
{
Changesets.Add(changesets[0]);
SelectedChangeset = changesets[0];
- SetMvvmFocus(RecentChangesetFocusableControlNames.ChangesetList);
+ SetMvvmFocus(ChangesetFocusableControlNames.ChangesetList);
UpdateTitle();
}
ShowAddByIdChangeset = false;
@@ -260,24 +161,20 @@ private static List GeChangesetIdsToAdd(string text)
return list;
}
- private void InvalidateCommands()
+ protected override void InvalidateCommands()
{
- ViewChangesetDetailsCommand.RaiseCanExecuteChanged();
+ base.InvalidateCommands();
+
ToggleAddByIdCommand.RaiseCanExecuteChanged();
CancelAddChangesetByIdCommand.RaiseCanExecuteChanged();
AddChangesetByIdCommand.RaiseCanExecuteChanged();
}
- public override void Dispose()
- {
- base.Dispose();
- _eventAggregator.GetEvent().Unsubscribe(OnMergeComplete);
- }
-
public override void SaveContext(object sender, SectionSaveContextEventArgs e)
{
base.SaveContext(sender, e);
- var context = new RecentChangesetsViewModelContext
+
+ var context = new RecentChangesetsSoloViewModelContext
{
ChangesetIdsText = ChangesetIdsText,
Changesets = Changesets,
@@ -289,9 +186,10 @@ public override void SaveContext(object sender, SectionSaveContextEventArgs e)
e.Context = context;
}
- private void RestoreContext(SectionInitializeEventArgs e)
+ protected override void RestoreContext(SectionInitializeEventArgs e)
{
- var context = (RecentChangesetsViewModelContext)e.Context;
+ var context = (RecentChangesetsSoloViewModelContext)e.Context;
+
ChangesetIdsText = context.ChangesetIdsText;
Changesets = context.Changesets;
SelectedChangeset = context.SelectedChangeset;
@@ -299,9 +197,12 @@ private void RestoreContext(SectionInitializeEventArgs e)
Title = context.Title;
}
- protected override void OnContextChanged(object sender, ContextChangedEventArgs e)
+ protected override string BaseTitle
{
- Refresh();
+ get
+ {
+ return Resources.RecentChangesetSectionName;
+ }
}
}
}
diff --git a/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModelContext.cs b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModelContext.cs
new file mode 100644
index 0000000..6a7853b
--- /dev/null
+++ b/src/AutoMerge/Changesets/Solo/RecentChangesetsSoloViewModelContext.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoMerge
+{
+ public class RecentChangesetsSoloViewModelContext : ChangesetsViewModelContext
+ {
+ public bool ShowAddByIdChangeset { get; set; }
+
+ public string ChangesetIdsText { get; set; }
+ }
+}
diff --git a/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml b/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml
new file mode 100644
index 0000000..11bee45
--- /dev/null
+++ b/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml.cs b/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml.cs
new file mode 100644
index 0000000..97d2867
--- /dev/null
+++ b/src/AutoMerge/Changesets/Team/TeamChangesetsView.xaml.cs
@@ -0,0 +1,16 @@
+using System.Windows.Controls;
+using Microsoft.TeamFoundation.Controls.MVVM;
+
+namespace AutoMerge
+{
+ ///
+ /// Interaction logic for TeamChangesetsView.xaml
+ ///
+ public partial class TeamChangesetsView : UserControl
+ {
+ public TeamChangesetsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/AutoMerge/Changesets/Team/TeamChangesetsViewModel.cs b/src/AutoMerge/Changesets/Team/TeamChangesetsViewModel.cs
new file mode 100644
index 0000000..cfb2fe7
--- /dev/null
+++ b/src/AutoMerge/Changesets/Team/TeamChangesetsViewModel.cs
@@ -0,0 +1,225 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMerge.Branches;
+using AutoMerge.Helpers;
+using AutoMerge.Prism.Command;
+using Microsoft.TeamFoundation.Controls;
+
+namespace AutoMerge
+{
+ public class TeamChangesetsViewModel : ChangesetsViewModel
+ {
+ private BranchTeamService _branchTeamService;
+ private TeamChangesetChangesetProvider _teamChangesetChangesetProvider;
+ private List _currentBranches;
+
+ public TeamChangesetsViewModel(ILogger logger) : base(logger)
+ {
+ SelectedChangesets = new ObservableCollection();
+ SourcesBranches = new ObservableCollection();
+ TargetBranches = new ObservableCollection();
+ ProjectNames = new ObservableCollection();
+
+ MergeCommand = DelegateCommand.FromAsyncHandler(MergeAsync, CanMerge);
+ FetchChangesetsCommand = DelegateCommand.FromAsyncHandler(FetchChangesetsAsync, CanFetchChangesets);
+ }
+
+ public DelegateCommand MergeCommand { get; private set; }
+ public DelegateCommand FetchChangesetsCommand { get; private set; }
+
+ public ObservableCollection ProjectNames { get; set; }
+ public ObservableCollection SourcesBranches { get; set; }
+ public ObservableCollection TargetBranches { get; set; }
+
+ private string _selectedProjectName;
+
+ public string SelectedProjectName
+ {
+ get { return _selectedProjectName; }
+ set
+ {
+ _selectedProjectName = value;
+ RaisePropertyChanged("SelectedProjectName");
+
+ _currentBranches = _teamChangesetChangesetProvider.ListBranches(SelectedProjectName);
+
+ Changesets.Clear();
+ SourcesBranches.Clear();
+ TargetBranches.Clear();
+ SourcesBranches.AddRange(_currentBranches.Select(x => x.Name));
+
+ UpdateTitle();
+ }
+ }
+
+ private string _sourceBranch;
+
+ public string SourceBranch
+ {
+ get { return _sourceBranch; }
+ set
+ {
+ _sourceBranch = value;
+ RaisePropertyChanged("SourceBranch");
+ InitializeTargetBranches();
+
+ FetchChangesetsCommand.RaiseCanExecuteChanged();
+ }
+ }
+
+ private string _targetBranch;
+
+ public string TargetBranch
+ {
+ get { return _targetBranch; }
+ set
+ {
+ _targetBranch = value;
+ RaisePropertyChanged("TargetBranch");
+
+ FetchChangesetsCommand.RaiseCanExecuteChanged();
+ }
+ }
+
+ private ObservableCollection _selectedChangesets;
+
+ public ObservableCollection SelectedChangesets
+ {
+ get { return _selectedChangesets; }
+ set
+ {
+ _selectedChangesets = value;
+ RaisePropertyChanged("SelectedChangesets");
+
+ if (_selectedChangesets != null)
+ {
+ _selectedChangesets.CollectionChanged += SelectedChangesets_CollectionChanged;
+ }
+ }
+ }
+
+ private void SelectedChangesets_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ MergeCommand.RaiseCanExecuteChanged();
+ }
+
+ private async Task MergeAsync()
+ {
+ await SetBusyWhileExecutingAsync(async () =>
+ {
+ var orderedSelectedChangesets = SelectedChangesets.OrderBy(x => x.ChangesetId).ToList();
+
+ await Task.Run(() => _branchTeamService.MergeBranches(SourceBranch, TargetBranch, orderedSelectedChangesets.First().ChangesetId, orderedSelectedChangesets.Last().ChangesetId));
+ _branchTeamService.AddWorkItemsAndNavigate(orderedSelectedChangesets.Select(x => x.ChangesetId));
+ });
+ }
+
+ private bool CanMerge()
+ {
+ return SelectedChangesets != null
+ && !IsBusy
+ && SelectedChangesets.Any()
+ && Changesets.Count(x => x.ChangesetId >= SelectedChangesets.Min(y => y.ChangesetId) &&
+ x.ChangesetId <= SelectedChangesets.Max(y => y.ChangesetId)) == SelectedChangesets.Count;
+ }
+
+ private async Task FetchChangesetsAsync()
+ {
+ await SetBusyWhileExecutingAsync(async () => await GetChangesetAndUpdateTitleAsync());
+
+ MergeCommand.RaiseCanExecuteChanged();
+ }
+
+ private bool CanFetchChangesets()
+ {
+ return SourceBranch != null && TargetBranch != null && !IsBusy;
+ }
+
+ protected override Task InitializeAsync(object sender, SectionInitializeEventArgs e)
+ {
+ _branchTeamService = new BranchTeamService(Context.TeamProjectCollection, (ITeamExplorer)ServiceProvider.GetService(typeof(ITeamExplorer)));
+ _teamChangesetChangesetProvider = new TeamChangesetChangesetProvider(ServiceProvider);
+
+ var projectNames = _teamChangesetChangesetProvider.ListProjects();
+ projectNames.ForEach(x => ProjectNames.Add(x.Name));
+
+ return base.InitializeAsync(sender, e);
+ }
+
+ public void InitializeTargetBranches()
+ {
+ TargetBranches.Clear();
+
+ if (SourceBranch != null)
+ {
+ TargetBranches.AddRange(_currentBranches.Single(x => x.Name == SourceBranch).Branches);
+ }
+ }
+
+ public override async Task> GetChangesetsAsync()
+ {
+ _teamChangesetChangesetProvider.SetSourceAndTargetBranch(SourceBranch, TargetBranch);
+ return await _teamChangesetChangesetProvider.GetChangesets();
+ }
+
+ public override void SaveContext(object sender, SectionSaveContextEventArgs e)
+ {
+ base.SaveContext(sender, e);
+
+ var context = new TeamChangesetsViewModelContext
+ {
+ SelectedProjectName = SelectedProjectName,
+ Changesets = Changesets,
+ Title = Title,
+ SourceBranch = SourceBranch,
+ TargetBranch = TargetBranch
+ };
+
+ e.Context = context;
+ }
+
+ protected override void RestoreContext(SectionInitializeEventArgs e)
+ {
+ var context = (TeamChangesetsViewModelContext)e.Context;
+
+ SelectedProjectName = context.SelectedProjectName;
+ Changesets = context.Changesets;
+ Title = context.Title;
+ SourceBranch = context.SourceBranch;
+ TargetBranch = context.TargetBranch;
+ }
+
+ public override void Loaded(object sender, SectionLoadedEventArgs e)
+ {
+ base.Loaded(sender, e);
+
+ //manually set to false because apparently HideBusy will set isBusy on false much later...
+ IsBusy = false;
+
+ MergeCommand.RaiseCanExecuteChanged();
+ FetchChangesetsCommand.RaiseCanExecuteChanged();
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+
+ if (_selectedChangesets != null)
+ {
+ _selectedChangesets.CollectionChanged -= SelectedChangesets_CollectionChanged;
+ }
+ }
+
+ protected override string BaseTitle
+ {
+ get
+ {
+ return "Project name: " + SelectedProjectName;
+ }
+ }
+
+ }
+}
diff --git a/src/AutoMerge/Changesets/Team/TeamChangesetsViewModelContext.cs b/src/AutoMerge/Changesets/Team/TeamChangesetsViewModelContext.cs
new file mode 100644
index 0000000..8771ee3
--- /dev/null
+++ b/src/AutoMerge/Changesets/Team/TeamChangesetsViewModelContext.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoMerge
+{
+ public class TeamChangesetsViewModelContext : ChangesetsViewModelContext
+ {
+ public string SourceBranch { get; set; }
+
+ public string TargetBranch { get; set; }
+
+ public string SelectedProjectName { get; set; }
+ }
+}
diff --git a/src/AutoMerge/Changesets/TeamChangesetsSection.cs b/src/AutoMerge/Changesets/TeamChangesetsSection.cs
new file mode 100644
index 0000000..f0ca209
--- /dev/null
+++ b/src/AutoMerge/Changesets/TeamChangesetsSection.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AutoMerge.Base;
+using Microsoft.TeamFoundation.Controls;
+using Microsoft.VisualStudio.Shell;
+
+namespace AutoMerge.RecentChangesets
+{
+ [TeamExplorerSection(GuidList.TeamChangesetsSectionId, GuidList.AutoMergeTeamPageId, 11)]
+ public class TeamChangesetsSection : TeamExplorerSectionBase
+ {
+ protected override ITeamExplorerSection CreateViewModel(SectionInitializeEventArgs e)
+ {
+ return base.CreateViewModel(e) ?? new TeamChangesetsViewModel(new VsLogger(ServiceProvider));
+ }
+
+ protected override object CreateView(SectionInitializeEventArgs e)
+ {
+ return new TeamChangesetsView();
+ }
+ }
+}
diff --git a/src/AutoMerge/Guids.cs b/src/AutoMerge/Guids.cs
index 661cd47..297dae0 100644
--- a/src/AutoMerge/Guids.cs
+++ b/src/AutoMerge/Guids.cs
@@ -1,4 +1,4 @@
-// Guids.cs
+// Guids.cs
// MUST match guids.h
using System;
@@ -12,9 +12,12 @@ public static class GuidList
public static readonly Guid guidAutoMergeCmdSet = new Guid(guidAutoMergeCmdSetString);
public const string AutoMergeNavigationItemId = "02A9D8B3-287B-4C55-83E7-7BFDB435546D";
- public const string AutoMergePageId = "3B582638-5F12-4715-8719-5E5777AB4581";
- public const string RecentChangesetsSectionId = "8DA59790-3996-465E-A13F-27D64B3C2A9D";
+ public const string AutoMergeTeamNavigationItemId = "3439f733-0177-4db4-b12b-85f19a4ac78a";
+ public const string AutoMergePageId = "3B582638-5F12-4715-8719-5E5777AB4581";
+ public const string AutoMergeTeamPageId = "246ccc66-d988-44d4-8d1e-e84ee846acd5";
+ public const string RecentChangesetsSectionId = "8DA59790-3996-465E-A13F-27D64B3C2A9D";
+ public const string TeamChangesetsSectionId = "b7dc6fbe-c3b1-47d8-805c-cce8c3dbedfb";
- public const string BranchesSectionId = "36BF6F52-F4AC-44A0-9985-817B2A65B3B0";
+ public const string BranchesSectionId = "36BF6F52-F4AC-44A0-9985-817B2A65B3B0";
};
-}
\ No newline at end of file
+}
diff --git a/src/AutoMerge/Helpers/CollectionExtensions.cs b/src/AutoMerge/Helpers/CollectionExtensions.cs
new file mode 100644
index 0000000..eff17c1
--- /dev/null
+++ b/src/AutoMerge/Helpers/CollectionExtensions.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace AutoMerge.Helpers
+{
+ public static class CollectionExtensions
+ {
+ public static void AddRange(this Collection list, IEnumerable itemsToAdd)
+ {
+ foreach(var itemToAdd in itemsToAdd)
+ {
+ list.Add(itemToAdd);
+ }
+ }
+ }
+}
diff --git a/src/AutoMerge/Helpers/ProjectNameHelper.cs b/src/AutoMerge/Helpers/ProjectNameHelper.cs
new file mode 100644
index 0000000..e876ad2
--- /dev/null
+++ b/src/AutoMerge/Helpers/ProjectNameHelper.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace AutoMerge
+{
+ public static class ProjectNameHelper
+ {
+ public static string GetProjectName(IServiceProvider serviceProvider)
+ {
+ var context = VersionControlNavigationHelper.GetTeamFoundationContext(serviceProvider);
+
+ if (context != null)
+ {
+ return context.TeamProjectName;
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/AutoMerge/Helpers/WorkspaceHelper.cs b/src/AutoMerge/Helpers/WorkspaceHelper.cs
index 4612c12..cf18cf7 100644
--- a/src/AutoMerge/Helpers/WorkspaceHelper.cs
+++ b/src/AutoMerge/Helpers/WorkspaceHelper.cs
@@ -1,5 +1,6 @@
-using System;
+using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
@@ -107,5 +108,15 @@ private static RegistryKey GetFeatureServerKey(string featurePath, string server
}
return null;
}
+
+ public static ObservableCollection GetWorkspaces(VersionControlServer versionControl, TfsTeamProjectCollection tfs)
+ {
+ var queryWorkspaces = versionControl.QueryWorkspaces(null, tfs.AuthorizedIdentity.UniqueName, Environment.MachineName);
+ if (queryWorkspaces.Length > 1)
+ {
+ return new ObservableCollection(queryWorkspaces.OrderBy(w => w.Name));
+ }
+ return new ObservableCollection(queryWorkspaces);
+ }
}
}
diff --git a/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs b/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs
deleted file mode 100644
index e8d65f2..0000000
--- a/src/AutoMerge/RecentChangesets/ChangesetByIdChangesetProvider.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace AutoMerge
-{
- public class ChangesetByIdChangesetProvider : ChangesetProviderBase
- {
- private readonly IEnumerable _changesetIds;
-
- public ChangesetByIdChangesetProvider(IServiceProvider serviceProvider, IEnumerable changesetIds)
- : base(serviceProvider)
- {
- if (changesetIds == null)
- throw new ArgumentNullException("changesetIds");
-
- _changesetIds = changesetIds;
- }
-
- protected override List GetChangesetsInternal(string userLogin)
- {
- var changesets = new List();
- var changesetService = GetChangesetService();
- if (changesetService != null)
- {
- changesets = _changesetIds
- .Select(changesetService.GetChangeset)
- .Where(c => c != null)
- .Select(tfsChangeset => ToChangesetViewModel(tfsChangeset, changesetService))
- .ToList();
- }
-
- return changesets;
- }
- }
-}
\ No newline at end of file
diff --git a/src/AutoMerge/RecentChangesets/IChangesetProvider.cs b/src/AutoMerge/RecentChangesets/IChangesetProvider.cs
deleted file mode 100644
index e140326..0000000
--- a/src/AutoMerge/RecentChangesets/IChangesetProvider.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
-namespace AutoMerge
-{
- public interface IChangesetProvider
- {
- Task> GetChangesets(string userLogin);
- }
-}
\ No newline at end of file
diff --git a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModelContext.cs b/src/AutoMerge/RecentChangesets/RecentChangesetsViewModelContext.cs
deleted file mode 100644
index 06ba726..0000000
--- a/src/AutoMerge/RecentChangesets/RecentChangesetsViewModelContext.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.ObjectModel;
-
-namespace AutoMerge
-{
- public class RecentChangesetsViewModelContext
- {
- public ChangesetViewModel SelectedChangeset { get; set; }
-
- public ObservableCollection Changesets { get; set; }
-
- public bool ShowAddByIdChangeset { get; set; }
-
- public string ChangesetIdsText { get; set; }
-
- public string Title { get; set; }
- }
-}
diff --git a/src/AutoMerge/Resources.Designer.cs b/src/AutoMerge/Resources.Designer.cs
index c2905fa..16c14ba 100644
--- a/src/AutoMerge/Resources.Designer.cs
+++ b/src/AutoMerge/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace AutoMerge {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -69,6 +69,15 @@ internal static string AutoMergePageName {
}
}
+ ///
+ /// Looks up a localized string similar to Auto Merge (Team).
+ ///
+ internal static string AutoMergeTeamPageName {
+ get {
+ return ResourceManager.GetString("AutoMergeTeamPageName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Target branches.
///
diff --git a/src/AutoMerge/Resources.resx b/src/AutoMerge/Resources.resx
index 27b993e..6534a6f 100644
--- a/src/AutoMerge/Resources.resx
+++ b/src/AutoMerge/Resources.resx
@@ -1,17 +1,17 @@
-
@@ -130,4 +130,7 @@
Resources\merge.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
+
+ Auto Merge (Team)
+
+
\ No newline at end of file
diff --git a/src/AutoMerge/Services/BranchTeamService.cs b/src/AutoMerge/Services/BranchTeamService.cs
new file mode 100644
index 0000000..7b150ed
--- /dev/null
+++ b/src/AutoMerge/Services/BranchTeamService.cs
@@ -0,0 +1,54 @@
+using Microsoft.TeamFoundation.Client;
+using Microsoft.TeamFoundation.Controls;
+using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer;
+using Microsoft.TeamFoundation.VersionControl.Client;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace AutoMerge
+{
+ public class BranchTeamService
+ {
+ private readonly Workspace _workspace;
+ private readonly ITeamExplorer _teamExplorer;
+ private readonly ChangesetService _changesetService;
+
+ public BranchTeamService(TfsTeamProjectCollection tfs, ITeamExplorer teamExplorer)
+ {
+ var versionControlServer = tfs.GetService();
+
+ _workspace = WorkspaceHelper.GetWorkspace(versionControlServer, WorkspaceHelper.GetWorkspaces(versionControlServer, tfs));
+ _teamExplorer = teamExplorer;
+ _changesetService = new ChangesetService(versionControlServer);
+ }
+
+ public void MergeBranches(string source, string target, int from, int to)
+ {
+ _workspace.Merge(source, target, new ChangesetVersionSpec(from), new ChangesetVersionSpec(to), LockLevel.None, RecursionType.Full, MergeOptions.None);
+ }
+
+ public void AddWorkItemsAndNavigate(IEnumerable changesetIds)
+ {
+ var workItemIds = new List();
+
+ foreach(var changesetId in changesetIds)
+ {
+ var changeSet = _changesetService.GetChangeset(changesetId);
+
+ if (changeSet != null && changeSet.AssociatedWorkItems != null)
+ {
+ workItemIds.AddRange(changeSet.AssociatedWorkItems.Select(x => x.Id));
+ }
+ }
+
+ var pendingChangePage = (TeamExplorerPageBase) _teamExplorer.NavigateToPage(new Guid(TeamExplorerPageIds.PendingChanges), null);
+ var pendingChangeModel = (IPendingCheckin) pendingChangePage.Model;
+
+ var modelType = pendingChangeModel.GetType();
+ var method = modelType.GetMethod("AddWorkItemsByIdAsync", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
+ method.Invoke(pendingChangeModel, new object[] { workItemIds.ToArray(), 1 });
+ }
+ }
+}
diff --git a/src/AutoMerge/Services/ChangesetService.cs b/src/AutoMerge/Services/ChangesetService.cs
index 612c2a7..81474f3 100644
--- a/src/AutoMerge/Services/ChangesetService.cs
+++ b/src/AutoMerge/Services/ChangesetService.cs
@@ -1,52 +1,95 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace AutoMerge
{
- public class ChangesetService
- {
- private readonly VersionControlServer _versionControlServer;
-
- public ChangesetService(VersionControlServer versionControlServer)
- {
- _versionControlServer = versionControlServer;
- }
-
- public ICollection GetUserChangesets(string teamProjectName, string userName, int count)
- {
- var path = "$/" + teamProjectName;
- return _versionControlServer.QueryHistory(path,
- VersionSpec.Latest,
- 0,
- RecursionType.Full,
- userName,
- null,
- null,
- count,
- false,
- true)
- .Cast()
- .ToList();
- }
-
- public Changeset GetChangeset(int changesetId)
- {
- var changeset = _versionControlServer.GetChangeset(changesetId, false, false);
-
- return changeset;
- }
-
- public Change[] GetChanges(int changesetId)
- {
- return _versionControlServer.GetChangesForChangeset(changesetId, false, int.MaxValue, null, null, null, true);
- }
-
- public List GetAssociatedBranches(params int[] changesetId)
- {
- var branches = _versionControlServer.QueryBranchObjectOwnership(changesetId);
-
- return branches.Select(b => b.RootItem).ToList();
- }
- }
+ public class ChangesetService
+ {
+ private readonly VersionControlServer _versionControlServer;
+
+ public ChangesetService(VersionControlServer versionControlServer)
+ {
+ _versionControlServer = versionControlServer;
+ }
+
+ public ICollection GetUserChangesets(string teamProjectName, string userName, int count)
+ {
+ var path = "$/" + teamProjectName;
+ return _versionControlServer.QueryHistory(path,
+ VersionSpec.Latest,
+ 0,
+ RecursionType.Full,
+ userName,
+ null,
+ null,
+ count,
+ false,
+ true)
+ .Cast()
+ .ToList();
+ }
+
+ public Changeset GetChangeset(int changesetId)
+ {
+ var changeset = _versionControlServer.GetChangeset(changesetId, false, false);
+
+ return changeset;
+ }
+
+
+ public Change[] GetChanges(int changesetId)
+ {
+ return _versionControlServer.GetChangesForChangeset(changesetId, false, int.MaxValue, null, null, null, true);
+ }
+
+ public List GetAssociatedBranches(params int[] changesetId)
+ {
+ var branches = _versionControlServer.QueryBranchObjectOwnership(changesetId);
+
+ return branches.Select(b => b.RootItem).ToList();
+ }
+
+
+ public ICollection GetMergeCandidates(string sourceBranch, string targetBranch)
+ {
+ var dummy = _versionControlServer.GetMergeCandidates(sourceBranch, targetBranch, RecursionType.Full);
+
+ List result = new List();
+
+ foreach (MergeCandidate mc in dummy)
+ {
+ result.Add(mc.Changeset);
+ }
+
+ return result;
+ }
+
+ public IEnumerable ListTfsProjects()
+ {
+ var result = _versionControlServer.GetAllTeamProjects(true);
+ return result;
+ }
+
+
+ public IEnumerable ListBranches(string projectName)
+ {
+ var dummy = _versionControlServer.QueryRootBranchObjects(RecursionType.Full);
+
+ var result = new List();
+ foreach(var bo in dummy)
+ {
+ var ro = bo.Properties.RootItem;
+
+ System.Diagnostics.Debug.WriteLine(ro.Item);
+
+ if (!ro.IsDeleted && ro.Item.Replace(@"$/", "").StartsWith(projectName + @"/"))
+ result.Add(bo);
+ }
+
+ return result;
+ }
+
+
+ }
}
diff --git a/src/AutoMerge/Styles/RecentChangesetResource.xaml b/src/AutoMerge/Styles/RecentChangesetResource.xaml
new file mode 100644
index 0000000..a220fde
--- /dev/null
+++ b/src/AutoMerge/Styles/RecentChangesetResource.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AutoMerge/UI/AutoMergeListBox.cs b/src/AutoMerge/UI/AutoMergeListBox.cs
new file mode 100644
index 0000000..c60df71
--- /dev/null
+++ b/src/AutoMerge/UI/AutoMergeListBox.cs
@@ -0,0 +1,40 @@
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace AutoMerge
+{
+ public class AutoMergeListBox : ListBox
+ {
+ public AutoMergeListBox()
+ {
+ SelectionChanged += AutoMergeListBox_SelectionChanged;
+ }
+
+ private void AutoMergeListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (SelectedItemsList != null)
+ {
+ foreach (var removedItem in e.RemovedItems.Cast())
+ {
+ SelectedItemsList.Remove(removedItem);
+ }
+
+ foreach (var addItem in e.AddedItems.Cast())
+ {
+ SelectedItemsList.Add(addItem);
+ }
+ }
+ }
+
+ public ObservableCollection SelectedItemsList
+ {
+ get { return (ObservableCollection)GetValue(SelectedItemsListProperty); }
+ set { SetValue(SelectedItemsListProperty, value); }
+ }
+
+ public static readonly DependencyProperty SelectedItemsListProperty =
+ DependencyProperty.Register("SelectedItemsList", typeof(ObservableCollection), typeof(AutoMergeListBox), new PropertyMetadata(null));
+ }
+}