sources/Google.Solutions.IapDesktop.Application/ToolWindows/Properties/PropertiesInspectorViewBase.cs (108 lines of code) (raw):

// // Copyright 2020 Google LLC // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // using Google.Solutions.Common.Diagnostics; using Google.Solutions.IapDesktop.Application.ToolWindows.ProjectExplorer; using Google.Solutions.IapDesktop.Core.ProjectModel; using Google.Solutions.Mvvm.Binding; using Google.Solutions.Mvvm.Controls; using Google.Solutions.Settings.Collection; using System; using System.ComponentModel; using System.Diagnostics; using System.Threading.Tasks; using System.Windows.Forms; using WeifenLuo.WinFormsUI.Docking; namespace Google.Solutions.IapDesktop.Application.ToolWindows.Properties { [SkipCodeCoverage("All logic in view model")] public abstract partial class PropertiesInspectorViewBase : ProjectExplorerTrackingToolWindow<IPropertiesInspectorViewModel> { private Bound<IPropertiesInspectorViewModel> viewModel; public PropertiesInspectorViewBase(IServiceProvider serviceProvider) : base(serviceProvider, DockState.DockRightAutoHide) { this.components = new System.ComponentModel.Container(); InitializeComponent(); } protected void Bind( IPropertiesInspectorViewModel viewModel, IBindingContext bindingContext) { this.viewModel.Value = viewModel; this.propertyGrid.EnableRichTextDescriptions(); this.panel.BindReadonlyObservableProperty( c => c.Text, viewModel, m => m.InformationText, bindingContext); this.BindReadonlyObservableProperty( c => c.Text, viewModel, m => m.WindowTitle, bindingContext); this.BindReadonlyObservableProperty( c => c.TabText, viewModel, m => m.WindowTitle, bindingContext); viewModel.InspectedObject.PropertyChanged += (_, __) => { SetInspectedObject(viewModel.InspectedObject.Value); }; } private void SetInspectedObject(object? obj) { Debug.Assert(this.viewModel.HasValue, "Bind has been called"); // // NB. The PropertyGrid displays a snapshot, if any of the // properties of the object changes, the grid does not // update automatically. // if (this.propertyGrid.SelectedObject is INotifyPropertyChanged oldObj) { oldObj.PropertyChanged -= RefreshOnPropertyChange; } if (obj is ISettingsCollection collection) { // Use a custom type descriptor to interpret each setting // as property. this.propertyGrid.SelectedObject = new SettingsCollectionTypeDescriptor(collection); } else { this.propertyGrid.SelectedObject = obj; } if (obj is INotifyPropertyChanged newObj) { newObj.PropertyChanged += RefreshOnPropertyChange; } } private void RefreshOnPropertyChange( object sender, PropertyChangedEventArgs args) { this.propertyGrid.Refresh(); } //--------------------------------------------------------------------- // ProjectExplorerTrackingToolWindow. //--------------------------------------------------------------------- protected override async Task SwitchToNodeAsync(IProjectModelNode node) { Debug.Assert(!this.InvokeRequired, "running on UI thread"); Debug.Assert(this.viewModel.HasValue, "Bind has been called"); await this.viewModel.Value.SwitchToModelAsync(node) .ConfigureAwait(true); } //--------------------------------------------------------------------- // Window event handlers. //--------------------------------------------------------------------- private void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) { this.viewModel.Value.SaveChanges(); } private void resetToolStripMenuItem_Click(object sender, EventArgs e) { var property = this.propertyGrid.SelectedGridItem?.PropertyDescriptor; if (property != null) { property.SetValue(this.propertyGrid.SelectedObject, null); // The grid does not notice this change, so we need to explicitly // save and refresh. this.viewModel.Value.SaveChanges(); this.propertyGrid.Refresh(); } } private void contextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) { var property = this.propertyGrid.SelectedGridItem?.PropertyDescriptor; this.resetToolStripMenuItem.Enabled = property != null && property.CanResetValue(this.propertyGrid.SelectedObject); } } }