File: Options\OptionPreviewControl.xaml.cs
Web Access
Project: src\src\VisualStudio\Core\Impl\Microsoft.VisualStudio.LanguageServices.Implementation.csproj (Microsoft.VisualStudio.LanguageServices.Implementation)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Linq;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options;
 
internal partial class OptionPreviewControl : AbstractOptionPageControl
{
    internal AbstractOptionPreviewViewModel ViewModel;
    private readonly IServiceProvider _serviceProvider;
    private readonly Func<OptionStore, IServiceProvider, AbstractOptionPreviewViewModel> _createViewModel;
 
    internal OptionPreviewControl(IServiceProvider serviceProvider, OptionStore optionStore, Func<OptionStore, IServiceProvider, AbstractOptionPreviewViewModel> createViewModel) : base(optionStore)
    {
        InitializeComponent();
 
        // AutomationDelegatingListView is defined in ServicesVisualStudio, which has
        // InternalsVisibleTo this project. But, the markup compiler doesn't consider the IVT 
        // relationship, so declaring the AutomationDelegatingListView in XAML would require 
        // duplicating that type in this project. Declaring and setting it here avoids the 
        // markup compiler completely, allowing us to reference the internal 
        // AutomationDelegatingListView without issue.
        var listview = new AutomationDelegatingListView();
        listview.Name = "Options";
        listview.SelectionMode = SelectionMode.Single;
        listview.PreviewKeyDown += Options_PreviewKeyDown;
        listview.SelectionChanged += Options_SelectionChanged;
        listview.SetBinding(ItemsControl.ItemsSourceProperty, new Binding { Path = new PropertyPath(nameof(ViewModel.Items)) });
        AutomationProperties.SetName(listview, ServicesVSResources.Options);
 
        listViewContentControl.Content = listview;
 
        _serviceProvider = serviceProvider;
        _createViewModel = createViewModel;
    }
 
    private void Options_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listView = (AutomationDelegatingListView)sender;
        if (listView.SelectedItem is AbstractCheckBoxViewModel checkbox)
        {
            ViewModel.UpdatePreview(checkbox.GetPreview());
        }
 
        if (listView.SelectedItem is AbstractRadioButtonViewModel radioButton)
        {
            ViewModel.UpdatePreview(radioButton.Preview);
        }
    }
 
    private void Options_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space && e.KeyboardDevice.Modifiers == ModifierKeys.None)
        {
            var listView = (AutomationDelegatingListView)sender;
            if (listView.SelectedItem is AbstractCheckBoxViewModel checkBox)
            {
                checkBox.IsChecked = !checkBox.IsChecked;
                e.Handled = true;
            }
 
            if (listView.SelectedItem is AbstractRadioButtonViewModel radioButton)
            {
                radioButton.IsChecked = true;
                e.Handled = true;
            }
        }
    }
 
    internal override void OnLoad()
    {
        this.ViewModel = _createViewModel(this.OptionStore, _serviceProvider);
 
        // Use the first item's preview.
        var firstItem = this.ViewModel.Items.OfType<CheckBoxOptionViewModel>().First();
        this.ViewModel.SetOptionAndUpdatePreview(firstItem.IsChecked, firstItem.Option, firstItem.GetPreview());
 
        DataContext = ViewModel;
    }
 
    internal override void Close()
    {
        base.Close();
 
        this.ViewModel?.Dispose();
    }
}