I have simple 2 buttons. Should I create 1 ICommand or is it ok now?
internal class MainPageViewModel : INotifyPropertyChanged
{
public ICommand RegisterBtnClickedCommand {get; }
public ICommand LoginBtnClickedCommand {get; }
public MainPageViewModel()
{
RegisterBtnClickedCommand = new Command(RegisterButtonPressed);
LoginBtnClickedCommand = new Command(LoginButtonPressed);
}
private void LoginButtonPressed()
{
Application.Current.MainPage.DisplayAlert("Login", "Login", "ok");
}
private void RegisterButtonPressed()
{
Application.Current.MainPage.DisplayAlert("Reg", "Reg", "ok");
}
public event PropertyChangedEventHandler PropertyChanged;
}
And for example, if I had 10 buttons, then I should have 10 commands?
And for example, if I had 10 buttons, then I should have 10 commands?
Yes.
Note that a single command might be invoked in different ways (button, menu entry, keyboard shortcut, unit test code), and that each command might have a different CanExecute logic. Thus, commands provide a convenient separation of concerns between the command itself (= your ICommand) and the way it is invoked (bindings in XAML).
If you are worried about too much boilerplate code, you can shorten your code slightly by initializing the property right at the point of declaration (rather than inside the constructor):
public ICommand RegisterBtnClickedCommand { get; } = new Command(RegisterButtonPressed);
...
Keep two separate commands for this. "Login" and "Register" are distinct enough actions. You can reuse commands for something like deleting an item from a list and pass in parameters to identify the item, but this is not the case here.
Though I wouldn't include Btn, Button, and Pressed in their names as they should be separated from any UI ideas (imagine a link being used later on instead of a button). I'd go with LoginCommand and LoginExecute for example.
Related
I'd like to find how to separate my GUI and work code.
The contrived example code, below, is the smallest starting point that
I can think of that covers the idea.
The example uses a Windows Form as the source of commands and as display
(consumer) of results. I want the work code to be capable of getting commands from, say, a command line interface instead. The work code should not depend on knowledge of the Form. The Form should know little about the work code. I'd like to have several consumers "see" when the property in the work code changes value.
I'm guessing this means using events for communication, and perhaps Interfaces as well, but I'm open to anything.
There are a million different suggestions out there. I've read the design pattern books, and I have tried many, and have yet to find a set that is well enough explained that I can fully implement it.
I don't want a universal solution. I want one as simple as possible
to implement and maintain for small, personal projects. I'm not
designing for a large corporation.
Most solutions I've found will hint at what to do, but not cover
the specifics like where an event is declared, and how the other
piece of code finds out about the event's existence so it can either issue
the event or respond to the event. I always end up needing, somewhere, what amounts to a global variable to hook things together.
The closest match I can find, here, to my question is this: C# Windows Forms App: Separate GUI from Business Logic But the solution uses the form to create an instance of the worker and returns a value directly, rather than informing any interested observers. The provided solution tightly bound the two classes.
The closest solution I've found anywhere is this: https://www.codeproject.com/Articles/14660/WinForms-Model-View-Presenter
which does some really cool work with interfaces and reflection, but didn't seem too maintainable nor flexible.
The comment lines in the source code below show the desired interaction
points but without the implementation.
File #1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// tell an instance of JustCounts to increment by 10
}
// Here, allow JustCounts to cause a call to this (or something
// similar, perhaps a property) to inform this code that the TotalCount
// property has changed.
public void ShowNewTotalCount(int NewTotal)
{
Console.WriteLine("New Total Count = {0}", NewTotal);
}
}
File #2
class JustCounts
{
private int m_TotalCount = 100;
// Inform other classes when the following property changes value,
// preferably including the value in the notification.
public int TotalCount { get => m_TotalCount; }
// The code in File #1 needs to result in a call to this method
// along with the correct argument value.
public void AddThisMuch(int increment)
{
m_TotalCount += increment;
}
}
I'm basing this on the current version of .Net (4.6.2).
If we implement INotifyPropertyChanged then we have an event that we can listen to for property changes. A bit like listening for key presses, we can filter then for the specific property that we want.
public class JustCounts : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private int m_totalCount = 100;
public int TotalCount
{
get { return m_totalCount; }
set
{
if (value != m_totalCount)
{
m_totalCount = value;
NotifyPropertyChanged();
}
}
}
}
There's no need to create a method to manipulate the TotalCount property as we're exposing it.
public class Form1 : Form
{
// justCounts is a reference to the object wherever it is coming from
justCounts.PropertyChanged += new PropertyChangedEventHandler(JustCountsChangedHandler);
private void JustCountsChangedHandler(object sender, PropertyChangingEventArgs e)
{
// process on event firing
Debug.WriteLine($"justCounts TotalCount changed value to {justCounts.TotalCount}");
}
// Example of where the handler will fire when called
private void button1_click(object sender, EventArgs e)
{
justCounts.TotalCount++;
}
}
In the code above, we've created an event in JustCounts to which listeners can subscribe.
Using the INotifyPropertyChanged interface, we fire the event each time TotalCount is changed.
In form 1 we create the handler to listen for property changes, and the handler then carries out any processing.
One note. You say
I'd like to have several consumers "see" when the property in the work
code changes value
so in order for this to work we have to assume that the work code can run independently of it's subscriber (something like a server). Otherwise, we'd have different instances for different subscribers.
You also mention interfaces, and they could be used but are not necessary in this instance.
I have been doing tons of research using MVVM (Model View ViewModel) with WPF. I am developing a desktop application. This application consists of a main window. This main window has some buttons which do something. Also, there is a button that opens a OpenFileDialog box.
Currently, this is my ViewModel to which the main window binds to:
MainWindowPresenter Class
namespace BMSVM_Simulator.ViewModel
{
class MainWindowPresenter : ObservableObject
{
private bool logLoaded; // true if a log is currently loaded, false otherwise
public MainWindowPresenter()
{
logLoaded = true;
}
public ICommand load_data_button_pressed
{
get { return new DelegateCommand(doLoadData); }
}
private void doLoadData()
{
// DO LOAD DATA COMMANDS
}
public ICommand exit_button_pressed
{
get { return new DelegateCommand(doExit); }
}
private void doExit()
{
// DO EXIT COMMANDS
}
}
}
QUESTION 1: I am concerned that this is the "wrong" implementation. Is it correct (per MVVM) for each button to have a property of type ICommand and then a corresponding method implementing the functionality? A main window with a lot of buttons would have a very large ViewModel class, no?
QUESTION 2: If one of the buttons was a File->Open File button. So, in that case it would open up a new OpenFileDialog window. Would this be done in the same way I previously done it above (i.e. have a public ICommand open_file_dialog_button_pressed property and a corresponding public void doOpenFileDialog() method? This seems like I am mixing the "view" of the open file dialog into the ViewModel, although the view is already defined by the built in wpf OpenFileDialog class.
QUESTION 3: Is it true that each "view" of our application should have only a single "presenter" class (which is part of the ViewModel) to which that view binds to? In the example above, my main window view binds to only the MainWindowPresenter class. If I were to make another view (say a graph generated with Microsoft's Dynamic Data Display library in it's own popout window), I would need an additional "presenter" class in my ViewModel, correct?
Thank you very much!
Rich
For reference, I've included these classes, but they may not be useful:
DelegateCommand Class
namespace BMSVM_Simulator.ViewModel
{
public class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
public bool CanExecute(object parameter)
{
return true;
}
#pragma warning disable 67
public event EventHandler CanExecuteChanged;
#pragma warning restore 67
}
}
ObservableObject Class
namespace BMSVM_Simulator.ViewModel
{
class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
//basic ViewModelBase
internal void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
}
}
1) Yes that's correct. You need to create a command property for each command. But thanks to your relay command you don't need to implement it directly. To prevent your ViewModel from busting i would recommend to move all commands into a separate CommandsViewModel serving as command source. Your View then binds to it.
2) Opening the Dialog can be achieved in XAML via routed commands using the CommandBinding property. So the tasks remains in the view. You basically try to avoid the dependency on any view related object. .NET provides some ready to use commands for common purposes (MSDN - ApplicationCommands)
3) You can share ViewModels among Views of course. That's one reason you structure your implementation into Model View ViewModel to be independent from changes and for reusability. It can become critical when more than one view is updating the same source simultaneously.
We have a large-ish app with a ribbon. The ribbon buttons are all bound to commands in my main view model (the data context of the main app window).
The constructor for MainViewModel is starting to grow as we create lots of RelayCommands (bound to the various ribbon commands). It looks something like this:
public MainWindowViewModel()
{
this.OpenProjectCommand = new RelayCommand(() =>
{
// buncha code
});
this.ProjectTypesCommand = new RelayCommand(() =>
{
// more code
});
this.NewSectionCommand = new RelayCommand(() =>
{
// code code code...
});
// ... only three ribbon buttons down, this is gonna get huge...
}
I'd prefer to have separate classes implementing each of the commands, rather than tons of inline code in MainViewModel's constructor. (Or creating lots of delegates in the MainViewModel, e.g. OpenProject, CanOpenProject, and then passing in references to them to the RelayCommand constructors).
Why don't I simply implement ICommand in a CommandBase and then create separate commands? Because I want to be "standard friendly" as per this question.
Is there a standard ICommand implementation I can use so that my commands are in separate classes?
I'd prefer not to add more MVVM frameworks into the mix since I'm already using MVVM Light. But I also don't want to reinvent the wheel.
Update: MainViewModel.cs doesn't need to be cluttered with scores of #regions or command methods. Extension methods aren't a good fit either IMHO.
The way I do is that I have "sub-viewmodels". For example, in the case of the MainViewModel, let's imagine that you have a PrintCommand and a CancelPrintCommand. You can have a new class called PrinterViewModel, and expose an instance of this class in the MainViewModel. Have the PrintCommand and the CancelPrintCommand in this PrinterViewModel (this also allows modular unit testing, which is neat).
Then in XAML:
Command="{Binding Main.Printer.PrintCommand}"
Alternatively, you could do
new RelayCommand(() => Printer.DoSomething())
Does that make sense?
Cheers
Laurent
You could at least create them in the getter.
You can use the ?? operator.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
This basically says: Return _testCommand, but create it first if it's still null.
This way, the command is not created until it's needed!
public class TestViewModel : ViewModelBase
{
#region OpenCommand
private RelayCommand _testCommand;
public RelayCommand TestCommand {
get {
return _testCommand = _testCommand
?? new RelayCommand(
this.ExecuteOpenCommand,
this.CanOpenCommandExecute);
}
}
private void ExecuteOpenCommand()
{
// do stuff
}
private bool CanOpenCommandExecute()
{
return true;
}
#endregion
}
If your goal is to organize, you can use #region and #endregion. And like we said, if your goal is to shrink the constructing process, use the ?? operator in getters. If you just hate inline code, create private methods in combination with RelayCommand, in getters.
I am creating an application that the user will be able to setup a series of functions to run on an object (image manipulation stuff).
Each different function has either no configurable options, or its own uniques set of options.
This is hard to explain, so let me show a simple example:
Image opened (always happens)
Remove border (two options)
Despeckle image (5 options)
Crop image (10 options)
Save image
The problem is that I need to allow the user to create a custom series of cleanup functions that will be used to process images in bulk.
What is the best way to go about this?
I'd highly recommend you look into the Command Pattern:
http://www.codeproject.com/KB/architecture/Command_Pattern.aspx
Essentially, this involves creating "Command" subclasses for each type of action the user can perform - and pushing them unto a stack once the command has been executed.
Each command knows how to "do" itself, and also "undo" itself.
Thus, undo is a relatively straight forward process of popping commands off the stack, and calling the undo method on them.
Because each instance of a Command can contain it's own state ("options"), you can create exactly the commands you want to use ahead of time, and "batch" them to get the result you are looking for.
pseudo-code:
public class ImageEditor
{
public Stack<Command> undoList = new Stack<Command>();
public void executeCommand(Command command)
{
command.performAction(this);
undoList.push(command);
}
public void undo()
{
undoList.peek().undoAction(this);
undoList.pop();
}
}
public interface ICommand
{
void performAction(ImageEditor editor);
void undoAction(ImageEditor editor);
}
public class CreateBorderCommand : ICommand
{
public int BorderWidth { get; set; }
private Border MyBorderBox { get; set; }
public void performAction(ImageEditor editor)
{
MyBorderBox = new Border(BorderWidth, editor.frame);
editor.addElement(MyBorderBox);
}
public void undoAction(ImageEditor editor)
{
editor.removeElement(MyBorderBox);
}
}
Later on:
ImageEditor editor = new ImageEditor();
editor.executeCommand(new CreateBorderCommand() { BorderWidth = 10 });
...
If you really want, you could make it a little more involved, and make all of the command definitions serializable - allowing you to create a list of them and read in the list and execute them later.
This can be solved by one of the standard 'Gang Of Four' design patterns. You should spend a bit of time reading about the Command Pattern. This pattern allows you to encapsulate the operations performed on an object within classes that implement the same interface. In your example, each of your steps becomes a command. Once you have a common interface for your commands you can then compose them into Macros.
I have a listbox that is bound to a List<T> -- this is working great.
I'd like to let my users double click a listbox item and open a new window that will display the "detail" view for that record. I'd like this new window to be databound to the same collection as the listbox on the original window. Because, that window has a timer, which polls a webserivce for updated data, I'd like the child (detail window) to also update when the main list updates.
Is this easily done? An example would be great, but any help is appreciated!
You could share the data directly (ie pass the SelectedItem reference to the child window), but that doesn't help you manage behavior and state across multiple windows. If it is a read-only view that's less of a problem, but if data is being changed it gets very problematic very quickly.
This is a good example of the benefits of using a Model-View-? pattern. MVVM is usually the preferred pattern for WPF because WPF is designed for complete separation-of-presentation. However, in a case like this, you may want something closer to MVC (Model-View-Controller), because you really want to coordinate behavior and state between distinct UI elements.
I would recommend a hybrid approach, let's call it "MVVMC" just to make the acronym even longer and more awkward. Implement a ViewModel that is completely UI-agnostic, and just exposes data and data-related state/behavior--probably mostly CRUD type stuff. Then implement a Controller specific to your UI design that consumes and exposes (either by delegation or composition) the ViewModel, but encapsulates. all of the the multi-window display behavior -- things enforcing one window per item, propagating close requests, etc.
public class MyViewModel : INotifyPropertyChanged, INotifyCollectionChanged
{
public MyViewModel(DataModel dataModel) { ... }
}
public class MyController
{
public MyController(MainWindow mainWindow, ViewModel viewModel) { ... }
public ViewModel { get { return _viewModel; } }
public ICommand DisplayChild { ... }
}
So what you're really doing is taking an MVVM, then inverting control so the controller can manage the multi-window UI. So the controller here would inject the ViewModel into windows (including main) as the DataContext for easy binding. It would also bind to events on the main window, launch child windows, and probably bind to child window events in order to manage them properly (eg one window per child record, close children when main closes, etc).
I would go one step further here, implementing the controller against an interface instead of Window. This gives you some flexibility in refactoring, but more importantly allows you to unit test your controller against mocks.
public interface IControllerChild
{
public void Show();
public bool Activate();
public void Close();
// add other behaviors here
}
public class DetailWindow : Window, IControllerChild
{
// implement other behaviors here
}
public class MockControllerChild : IControllerChild
{
public void Show() { IsShowing = true; ActionLog.Add(MockControllerAction.Show); }
public void Activate() { IsShowing = false; ActionLog.Add(MockControllerAction.Activate); }
public void Close() { IsShowing = false; ActionLog.Add(MockControllerAction.Close); }
public bool IsShowing { get; private set; }
public IList<MockControllerAction> ActionLog { get; private set; }
// mock and record other behaviors here
}
public enum MockControllerAction
{
Show,
Activate,
Close,
// Add other behaviors here
};