public MainForm(MainViewModel viewModel) { InitializeComponent(); this.viewModel = viewModel; grid.AutoGenerateColumns = true; errorProvider.Icon = Images.Error; warningProvider.Icon = Images.Warning; infoProvider.Icon = Images.Information; // For the better overview even the standard WinForms bindings are set here instead of the designer. // listBindingSource -> grid/listBox/errorProvider/tbIntPropList/tbStringPropList/editMenuStrip tbIntPropList.DataBindings.Add(nameof(TextBox.Text), listBindingSource, nameof(ITestObject.IntProp)); tbStringPropList.DataBindings.Add(nameof(TextBox.Text), listBindingSource, nameof(ITestObject.StringProp)); editMenuStrip.DataBindings.Add(nameof(editMenuStrip.DataSource), listBindingSource, String.Empty); // itemBindingSource -> tbIntPropCurrent/tbStringPropCurrent tbIntPropCurrent.DataBindings.Add(nameof(TextBox.Text), itemBindingSource, nameof(ITestObject.IntProp)); tbStringPropCurrent.DataBindings.Add(nameof(TextBox.Text), itemBindingSource, nameof(ITestObject.StringProp)); // A ToolStripButton does not support regular WinForms binding. But as it has a CheckedChanged event, KGy SOFT's command binding can be used for it. // btnChangeInner.Checked -> viewModel.ChangeUnderlyingCollection - AddPropertyBinding will use an internal command for the change event. commandBindings.AddPropertyBinding(btnChangeInner, nameof(btnChangeInner.Checked), nameof(viewModel.ChangeUnderlyingCollection), viewModel); // Binding radio buttons by KGy SOFT's command binding, too (regular WinForms binding behaves strangely for radio buttons). commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseList), rbList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseBindingList), rbBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseSortableBindingList), rbSortableBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseSortableBindingListSortOnChange), rbSortableBindingListSortOnChange, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseObservableCollection), rbObservableCollection, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseObservableBindingList), rbObservableBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.NoInnerList), rbNoInnerList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.InnerList), rbInnerList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.InnerBindingList), rbInnerBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.InnerSortableBindingList), rbInnerSortableBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.InnerObservableCollection), rbInnerObservableCollection, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.InnerObservableBindingList), rbInnerObservableBindingList, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UsePlainTestObject), rbObject, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseObservableTestObject), rbObservableObject, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseUndoableTestObject), rbUndoable, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseEditableTestObject), rbEditable, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseValidatingTestObject), rbValidating, nameof(RadioButton.Checked)); commandBindings.AddTwoWayPropertyBinding(viewModel, nameof(viewModel.UseAllInOneTestObject), rbModel, nameof(RadioButton.Checked)); // Binding to ViewModel Commands. Using a shared state for the indexing commands so we can set their Enabled status at once. // Adding PropertyCommandStateUpdater.Updater to them so their source buttons will reflect the Enabled state. commandsWithCurrentItemState = new CommandState { Enabled = false }; commandBindings.Add(viewModel.AddItemCommand, btnAdd, nameof(btnAdd.Click)); // btnAdd.Click -> viewModel.AddItemCommand commandBindings.Add(viewModel.RemoveItemCommand, commandsWithCurrentItemState) // btnRemove.Click -> viewModel.RemoveItemCommand .WithParameter(() => listBindingSource.Current) .AddStateUpdater(PropertyCommandStateUpdater.Updater) .AddSource(btnRemove, nameof(btnRemove.Click)); commandBindings.Add(viewModel.SetItemCommand, commandsWithCurrentItemState) // btnSetItem.Click -> viewModel.SetItemCommand .WithParameter(() => listBindingSource.Current) .AddStateUpdater(PropertyCommandStateUpdater.Updater) .AddSource(btnSetItem, nameof(btnSetItem.Click)); commandBindings.Add(viewModel.SetItemPropertyCommand, commandsWithCurrentItemState) // btnSetProp.Click -> viewModel.SetItemPropertyCommand .WithParameter(() => listBindingSource.Current) .AddStateUpdater(PropertyCommandStateUpdater.Updater) .AddSource(btnSetProp, nameof(btnSetProp.Click)); // Note that the following bindings don't reference any explicitly defined ICommands instances. We can do this for private commands not used by anyone else. commandBindings.Add <CommandErrorEventArgs>(OnCommandErrorHandler) // viewModel.CommandError -> OnCommandErrorHandler .AddSource(viewModel, nameof(viewModel.CommandError)); commandBindings.Add <EventArgs>(OnRebindCommand) // this.Load/viewModel.PropertyChanged -> OnRebindCommand .AddSource(this, nameof(Load)) .AddSource(viewModel, nameof(MainViewModel.PropertyChanged)); commandBindings.Add(() => { }).AddSource(grid, nameof(grid.DataError)); // grid.DataError: adding an empty handler so no dialogs will be popped up endlessly on errors commandBindings.Add <EventArgs>(OnListBindingSourceCurrentItemChangedCommand) // listBindingSource.CurrentItemChanged -> OnListBindingSourceCurrentItemChangedCommand .AddSource(listBindingSource, nameof(listBindingSource.CurrentItemChanged)); commandBindings.Add(OnResetBindingCommand).AddSource(btnReset, nameof(btnReset.Click)); // btnReset.Click -> OnResetBindingCommand // even static events are supported, provide a type as source: commandBindings.Add <ThreadExceptionEventArgs>(OnApplicationThreadExceptionCommand) // Application.ThreadException -> OnApplicationThreadExceptionCommand .AddSource(typeof(Application), nameof(Application.ThreadException)); }