Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit ab8b581

Browse files
authored
Merge branch 'master' into jcansdale/TeamExplorer2017
2 parents 782fdb1 + ba29d80 commit ab8b581

File tree

312 files changed

+6955
-9424
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

312 files changed

+6955
-9424
lines changed

GitHubVS.sln

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Api", "src\GitHub.Ap
5858
EndProject
5959
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Exports.Reactive", "src\GitHub.Exports.Reactive\GitHub.Exports.Reactive.csproj", "{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}"
6060
EndProject
61-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesignTimeStyleHelper", "src\DesignTimeStyleHelper\DesignTimeStyleHelper.csproj", "{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}"
62-
EndProject
6361
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Octokit", "Octokit", "{1E7F7253-A6AF-43C4-A955-37BEDDA01AC0}"
6462
EndProject
6563
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octokit", "submodules\octokit.net\Octokit\Octokit.csproj", "{08DD4305-7787-4823-A53F-4D0F725A07F3}"
@@ -215,16 +213,6 @@ Global
215213
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.Release|Any CPU.Build.0 = Release|Any CPU
216214
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
217215
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
218-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
219-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
220-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugCodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
221-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugCodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
222-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugWithoutVsix|Any CPU.ActiveCfg = Debug|Any CPU
223-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugWithoutVsix|Any CPU.Build.0 = Debug|Any CPU
224-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
225-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Release|Any CPU.Build.0 = Release|Any CPU
226-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
227-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
228216
{08DD4305-7787-4823-A53F-4D0F725A07F3}.Debug|Any CPU.ActiveCfg = Release|Any CPU
229217
{08DD4305-7787-4823-A53F-4D0F725A07F3}.Debug|Any CPU.Build.0 = Release|Any CPU
230218
{08DD4305-7787-4823-A53F-4D0F725A07F3}.DebugCodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: '2.3.5.{build}'
1+
version: '2.3.7.{build}'
22
skip_tags: true
33
install:
44
- ps: |

build.cmd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
powershell -ExecutionPolicy Unrestricted scripts\build.ps1 %1
1+
@if "%1" == "" echo Please specify Debug or Release && EXIT /B
2+
powershell -ExecutionPolicy Unrestricted scripts\build.ps1 -Package:$true -Config:%1

docs/contributing/creating-an-empty-repository-from-visual-studio.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Creating an empty repository from Visual Studio
22

3-
1. [Sign in](authenticating-to-github) to GitHub.
3+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
44

55
2. Open **Team Explorer** by clicking on its tab next to *Solution Explorer*, or via the *View* menu.
66

docs/contributing/creating-gists.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
GitHub for Visual Studio enables easy creation of gists directly from the Visual Studio Editor.
44

5-
1. [Sign in](authenticating-to-github) to GitHub.
5+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
66

77
2. Open a file in the Visual Studio text editor.
88

docs/contributing/viewing-the-pull-requests-for-a-repository.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
GitHub for Visual Studio exposes the pull requests for the current repository and lets you create new pull requests and review pull requests from other contributors.
44

5-
1. [Sign in](authenticating-to-github) to GitHub.
5+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
66
2. Open a solution in a GitHub repository.
77
3. Open **Team Explorer** and click the **Pull Requests** button to open the **GitHub** pane.
88
![Pull Requests button in the Team Explorer pane](images/pull-requests-button2.png)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Dialog Views with Connections
2+
3+
Some dialog views need a connection to operate - if there is no connection, a login dialog should be shown: for example, clicking Create Gist without a connection will first prompt the user to log in.
4+
5+
Achieving this is simple, first make your view model interface implement `IConnectionInitializedViewModel` and do any initialization that requires a connection in the `InitializeAsync` method in your view model:
6+
7+
```csharp
8+
public Task InitializeAsync(IConnection connection)
9+
{
10+
// .. at this point, you're guaranteed to have a connection.
11+
}
12+
```
13+
14+
To show the dialog, call `IShowDialogService.ShowWithFirstConnection` instead of `Show`:
15+
16+
```csharp
17+
public async Task ShowExampleDialog()
18+
{
19+
var viewModel = serviceProvider.ExportProvider.GetExportedValue<IExampleDialogViewModel>();
20+
await showDialog.ShowWithFirstConnection(viewModel);
21+
}
22+
```
23+
24+
`ShowFirstConnection` first checks if there are any logged in connections. If there are, the first logged in connection will be passed to `InitializeAsync` and the view shown immediately. If there are no logged in connections, the login view will first be shown. Once the user has successfully logged in, the new connection will be passed to `InitalizeAsync` and the view shown.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# How ViewModels are Turned into Views
2+
3+
We make use of the [MVVM pattern](https://msdn.microsoft.com/en-us/library/ff798384.aspx), in which application level code is not aware of the view level. MVVM takes advantage of the fact that `DataTemplate`s can be used to create views from view models.
4+
5+
## DataTemplates
6+
7+
[`DataTemplate`](https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview)s are a WPF feature that allow you to define the presentation of your data. Consider a simple view model:
8+
9+
```csharp
10+
public class ViewModel
11+
{
12+
public string Greeting => "Hello World!";
13+
}
14+
```
15+
16+
And a window:
17+
18+
```csharp
19+
public class MainWindow : Window
20+
{
21+
public MainWindow()
22+
{
23+
DataContext = new ViewModel();
24+
InitializeComponent();
25+
}
26+
}
27+
```
28+
29+
```xml
30+
<Window x:Class="MyApp.MainWindow"
31+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
32+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33+
xmlns:local="clr-namespace:MyApp"
34+
Content="{Binding}">
35+
<Window>
36+
37+
```
38+
39+
Here we're binding the `Content` of the `Window` to the `Window.DataContext`, which we're setting in the constructor to be an instance of `ViewModel`.
40+
41+
One can choose to display the `ViewModel` instance in any way we want by using a `DataTemplate`:
42+
43+
```xml
44+
<Window x:Class="MyApp.MainWindow"
45+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
46+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
47+
xmlns:local="clr-namespace:MyApp"
48+
Content="{Binding}">
49+
<Window.Resources>
50+
<DataTemplate DataType="{x:Type local:ViewModel}">
51+
52+
<!-- Display ViewModel.Greeting in a red border with rounded corners -->
53+
<Border Background="Red" CornerRadius="8">
54+
<TextBlock Binding="{Binding Greeting}"/>
55+
</Border>
56+
57+
</DataTemplate>
58+
</Window.Resources>
59+
</Window>
60+
```
61+
62+
This is the basis for converting view models to views.
63+
64+
## ViewLocator
65+
66+
There are currently two top-level controls for our UI:
67+
68+
- [GitHubDialogWindow](../src/GitHub.VisualStudio/Views/Dialog/GitHubDialogWindow.xaml) for the dialog which shows the login, clone, etc views
69+
- [GitHubPaneView](../src/GitHub.VisualStudio/Views/GitHubPane/GitHubPaneView.xaml) for the GitHub pane
70+
71+
In the resources for each of these top-level controls we define a `DataTemplate` like so:
72+
73+
```xml
74+
<views:ViewLocator x:Key="viewLocator"/>
75+
<DataTemplate DataType="{x:Type vm:ViewModelBase}">
76+
<ContentControl Content="{Binding Converter={StaticResource viewLocator}}"/>
77+
</DataTemplate>
78+
```
79+
80+
The `DataTemplate.DataType` here applies the template to all classes inherited from [`GitHub.ViewModels.ViewModelBase`](../src/GitHub.Exports.Reactive/ViewModels/ViewModelBase.cs) [1]. The template defines a single `ContentControl` whose contents are created by a `ViewLocator`.
81+
82+
The [`ViewLocator`](../src/GitHub.VisualStudio/Views/ViewLocator.cs) class is an `IValueConverter` which then creates an instance of the appropriate view for the view model using MEF.
83+
84+
And thus a view model becomes a view.
85+
86+
[1]: it would be nice to make it apply to all classes that inherit `IViewModel` but unfortunately WPF's `DataTemplate`s don't work with interfaces.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Implementing a Dialog View
2+
3+
GitHub for Visual Studio has a common dialog which is used to show the login, clone, create repository etc. operations. To add a new view to the dialog and show the dialog with this view, you need to do the following:
4+
5+
## Create a View Model and Interface
6+
7+
- Create an interface for the view model that implements `IDialogContentViewModel` in `GitHub.Exports.Reactive\ViewModels\Dialog`
8+
- Create a view model that inherits from `NewViewModelBase` and implements the interface in `GitHub.App\ViewModels\Dialog`
9+
- Export the view model with the interface as the contract and add a `[PartCreationPolicy(CreationPolicy.NonShared)]` attribute
10+
11+
A minimal example that just exposes a command that will dismiss the dialog:
12+
13+
```csharp
14+
using System;
15+
using ReactiveUI;
16+
17+
namespace GitHub.ViewModels.Dialog
18+
{
19+
public interface IExampleDialogViewModel : IDialogContentViewModel
20+
{
21+
ReactiveCommand<object> Dismiss { get; }
22+
}
23+
}
24+
```
25+
26+
```csharp
27+
using System;
28+
using System.ComponentModel.Composition;
29+
using ReactiveUI;
30+
31+
namespace GitHub.ViewModels.Dialog
32+
{
33+
[Export(typeof(IExampleDialogViewModel))]
34+
[PartCreationPolicy(CreationPolicy.NonShared)]
35+
public class ExampleDialogViewModel : ViewModelBase, IExampleDialogViewModel
36+
{
37+
[ImportingConstructor]
38+
public ExampleDialogViewModel()
39+
{
40+
Dismiss = ReactiveCommand.Create();
41+
}
42+
43+
public string Title => "Example Dialog";
44+
45+
public ReactiveCommand<object> Dismiss { get; }
46+
47+
public IObservable<object> Done => Dismiss;
48+
}
49+
}
50+
```
51+
52+
## Create a View
53+
54+
- Create a WPF `UserControl` under `GitHub.VisualStudio\Views\Dialog`
55+
- Add an `ExportViewFor` attribute with the type of the view model interface
56+
- Add a `PartCreationPolicy(CreationPolicy.NonShared)]` attribute
57+
58+
Continuing the example above:
59+
60+
```xml
61+
<UserControl x:Class="GitHub.VisualStudio.Views.Dialog.ExampleDialogView"
62+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
63+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
64+
<Button Command="{Binding Dismiss}" HorizontalAlignment="Center" VerticalAlignment="Center">
65+
Dismiss
66+
</Button>
67+
</UserControl>
68+
```
69+
70+
```csharp
71+
using System.ComponentModel.Composition;
72+
using System.Windows.Controls;
73+
using GitHub.Exports;
74+
using GitHub.ViewModels.Dialog;
75+
76+
namespace GitHub.VisualStudio.Views.Dialog
77+
{
78+
[ExportViewFor(typeof(IExampleDialogViewModel))]
79+
[PartCreationPolicy(CreationPolicy.NonShared)]
80+
public partial class ExampleDialogView : UserControl
81+
{
82+
public ExampleDialogView()
83+
{
84+
InitializeComponent();
85+
}
86+
}
87+
}
88+
```
89+
90+
## Show the Dialog!
91+
92+
To show the dialog you will need an instance of the `IShowDialogService` service. Once you have that, simply call the `Show` method with an instance of your view model.
93+
94+
```csharp
95+
var viewModel = new ExampleDialogViewModel();
96+
showDialog.Show(viewModel)
97+
```
98+
99+
## Optional: Add a method to `DialogService`
100+
101+
Creating a view model like this may be the right thing to do, but it's not very reusable or testable. If you want your dialog to be easy reusable, add a method to `DialogService`:
102+
103+
```csharp
104+
public async Task ShowExampleDialog()
105+
{
106+
var viewModel = factory.CreateViewModel<IExampleDialogViewModel>();
107+
await showDialog.Show(viewModel);
108+
}
109+
```
110+
111+
Obviously, add this method to `IDialogService` too.
112+
113+
Note that these methods are `async` - this means that if you need to do asynchronous initialization of your view model, you can do it here before calling `showDialog`.

0 commit comments

Comments
 (0)