public MainWindow(MainViewModel viewModel) { // Initialization of a pure WPF command. // SimpleWpfCommand is actually a usual "relay" or "delegate" command. ResetBindingCommand = new SimpleWpfCommand(OnResetBindingCommand); // Initialization of a simple KGy SOFT command. The difference is only the access of these properties from XAML. // Instead of the XAML way we could have written: commandBindings.Add(new SimpleCommand(OnWindowClosedCommand)).AddSource(this, "Closed"); WindowClosedCommand = new SimpleCommand(OnWindowClosedCommand); // Similarly, this could have been purely initialized from C# and then we didn't need the public property. See also the examples below. AutoGeneratingColumnCommand = new SourceAwareCommand <DataGridAutoGeneratingColumnEventArgs>(OnAutoGeneratingColumnCommand); InitializeComponent(); DataContext = viewModel; this.viewModel = viewModel; // And of course we always can use a CommandBindingsCollection instance to create command bindings for any events. // This is highly recommended for events of objects that can outlive our window so we can release all of the handlers // at once by disposing the CommandBindingsCollection. See also the WindowClosedCommand. // Application.Current.DispatcherUnhandledException -> OnCurrentDispatcherUnhandledExceptionCommand // Note that we use an implicit command here. It is the shorthand of .Add(new SourceAwareCommand<DispatcherUnhandledExceptionEventArgs>(OnCurrentDispatcherUnhandledExceptionCommand)) commandBindings.Add <DispatcherUnhandledExceptionEventArgs>(OnCurrentDispatcherUnhandledExceptionCommand) .AddSource(Application.Current, nameof(Application.DispatcherUnhandledException)); // viewModel.PropertyChanged -> OnViewModelPropertyChangedCommand; commandBindings.Add <PropertyChangedEventArgs>(OnViewModelPropertyChangedCommand) .AddSource(viewModel, nameof(viewModel.PropertyChanged)); UpdateCurrentView(); }
public DebuggerTestForm() { InitializeComponent(); cmbPixelFormat.DataSource = viewModel.PixelFormats; commandBindings.AddPropertyBinding(chbAsImage, nameof(CheckBox.Checked), nameof(viewModel.AsImage), viewModel); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.PixelFormat), nameof(ComboBox.SelectedItem), cmbPixelFormat); commandBindings.AddPropertyBinding(cmbPixelFormat, nameof(ComboBox.SelectedValue), nameof(viewModel.PixelFormat), viewModel); commandBindings.AddPropertyBinding(rbBitmap, nameof(RadioButton.Checked), nameof(viewModel.Bitmap), viewModel); commandBindings.AddPropertyBinding(rbMetafile, nameof(RadioButton.Checked), nameof(viewModel.Metafile), viewModel); commandBindings.AddPropertyBinding(rbHIcon, nameof(RadioButton.Checked), nameof(viewModel.HIcon), viewModel); commandBindings.AddPropertyBinding(rbManagedIcon, nameof(RadioButton.Checked), nameof(viewModel.ManagedIcon), viewModel); commandBindings.AddPropertyBinding(rbGraphicsBitmap, nameof(RadioButton.Checked), nameof(viewModel.GraphicsBitmap), viewModel); commandBindings.AddPropertyBinding(rbGraphicsHwnd, nameof(RadioButton.Checked), nameof(viewModel.GraphicsHwnd), viewModel); commandBindings.AddPropertyBinding(rbBitmapData, nameof(RadioButton.Checked), nameof(viewModel.BitmapData), viewModel); commandBindings.AddPropertyBinding(rbPalette, nameof(RadioButton.Checked), nameof(viewModel.Palette), viewModel); commandBindings.AddPropertyBinding(rbColor, nameof(RadioButton.Checked), nameof(viewModel.SingleColor), viewModel); commandBindings.AddPropertyBinding(rbFromFile, nameof(RadioButton.Checked), nameof(viewModel.ImageFromFile), viewModel); commandBindings.AddPropertyBinding(tbFile, nameof(tbFile.Text), nameof(viewModel.FileName), viewModel); commandBindings.AddPropertyBinding(rbAsImage, nameof(RadioButton.Checked), nameof(viewModel.FileAsImage), viewModel); commandBindings.AddPropertyBinding(rbAsBitmap, nameof(RadioButton.Checked), nameof(viewModel.FileAsBitmap), viewModel); commandBindings.AddPropertyBinding(rbAsMetafile, nameof(RadioButton.Checked), nameof(viewModel.FileAsMetafile), viewModel); commandBindings.AddPropertyBinding(rbAsIcon, nameof(RadioButton.Checked), nameof(viewModel.FileAsIcon), viewModel); commandBindings.AddPropertyBinding(chbAsReadOnly, nameof(CheckBox.Checked), nameof(viewModel.AsReadOnly), viewModel); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.AsImageEnabled), nameof(chbAsImage.Enabled), chbAsImage); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.PixelFormatEnabled), nameof(cmbPixelFormat.Enabled), cmbPixelFormat); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.ImageFromFile), nameof(gbFile.Enabled), gbFile); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.AsReadOnlyEnabled), nameof(chbAsReadOnly.Enabled), chbAsReadOnly); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.CanDebug), nameof(Button.Enabled), btnViewDirect, btnViewByDebugger); commandBindings.AddPropertyBinding(viewModel, nameof(viewModel.PreviewImage), nameof(pictureBox.Image), pictureBox); commandBindings.Add <EventArgs>(OnSelectFileCommand) .AddSource(tbFile, nameof(tbFile.Click)) .AddSource(tbFile, nameof(tbFile.DoubleClick)); commandBindings.Add(viewModel.DirectViewCommand).AddSource(btnViewDirect, nameof(btnViewDirect.Click)); commandBindings.Add(viewModel.DebugCommand).AddSource(btnViewByDebugger, nameof(btnViewByDebugger.Click)); viewModel.GetHwndCallback = () => Handle; viewModel.GetClipCallback = () => pictureBox.Bounds; // Due to some strange issue on Linux the app crashes if we show a MessageBox while changing radio buttons // so as a workaround we show error messages by using a timer. Another solution would be to show a custom dialog. timer = new Timer { Interval = 1 }; viewModel.ErrorCallback = message => { errorMessage = message; timer.Enabled = true; }; commandBindings.Add(OnShowErrorCommand) .AddSource(timer, nameof(timer.Tick)); }
internal static ICommandBinding AddPropertyChangedHandler(this CommandBindingsCollection collection, Action handler, INotifyPropertyChanged source, params string[] propertyNames) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } if (propertyNames == null) { throw new ArgumentNullException(nameof(propertyNames)); } var state = new Dictionary <string, object> { [stateHandler] = handler, [statePropertyNames] = propertyNames }; return(collection.Add(propertyChangedCommand, state) .AddSource(source, nameof(source.PropertyChanged))); }
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)); }