I'm just starting out with WPF and I want to use custom commands whenever possible as part of the MVVM pattern. The book that I've been using (C# 2010 All-in-One for Dummies) has a sample of a custom command but it uses hard coded information to complete its task and I don't see how to use the Command system to complete my task.
Book Code:
public abstract class CommandBase : ICommand
{
public string Text { get; internal set; }
public abstract void Execute(object parameter);
public abstract bool CanExecute(object parameter);
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
public class AddCustomerCommand : CommandBase
{
public AddCustomerCommand()
{
Text = “Add Customer”;
}
public override void Execute(object parameter)
{
var list = parameter as IList<Customer>;
if (list == null)
{
return;
}
list.Add(new Customer { ID = 4, Name = “New Customer”} );
}
public override bool CanExecute(object parameter)
{
return parameter is IList<Customer>;
}
}
In this case, Execute works because it is passed an IList<Customer> and can add to it without needing to return anything. This makes perfect sense to me.
My Problem:
I have an MVVM app that has a data grid, some text boxes, and some buttons. My view model has IList<Entry> Entries, properties for the text boxes, and of course an instance of my custom command AddEntryCommand. The goal is to be able to enter text, and hit add, and have a new Entry be added to Entries using AddEntryCommand.
What I don't understand is how to go about getting Entries and the new data into the command. Here are the possible solutions I've thought of and what I see wrong with them
Pass in the view model so that all its information is available.
Pass in an array of objects.
Pass in a Tuple.
Passing thew view model seems excessive, and if I do that then everything on the view model would have to be mutable.
I try and avoid using object whenever possible, and object[] seems even more work to deal with. I'd have to pick it apart like command line arguments.
Tuples...
My idea of a command is that it's supposed to be a method with bells and whistles for making the UI react nicely. Anything that causes the command to be tied to a specific view or view model breaks that.
So my questions are:
How do you do work with multiple objects using ICommand?
How can you use ICommand to work with immutable objects if it's locked to return void?
Is my idea of what a command is for way off base?
(I've tried searching for a better tutorial or resource for this but my Google fu is weak and I can't seem to locate anything that's clear and concise. There are lots of questions on SO about commands in WPF, but they're all for very specific implementations. I'm looking for a general answer regarding manipulating multiple objects in one command.)
UPDATE
I have been looking around the net some more but I still haven't found anything like the sample provided by my book. I have looked at DelegateCommand and that seems like a pretty straightforward and easy to use system. It still leaves me wondering why such a large chunk of the chapter on MVVM would be dedicated to creating a custom command using just ICommand and not one of the other classes that already inherit from it.
Related
I am recoding a WinForms app (MySQL/EF6 with many fields to update) using WPF. I am examining code required to support INotifyPropertyChanged for each field, and wondering if this is an advantage over classic code behind event handling.
I have developed a robust WinForms app in C# supporting a fairly complex data model including EF6/MySQL. As you can imagine, with many text fields, combo boxes, NumUpDowns etc, there are many event handlers for all the different fields. As I look at moving this code base to WPF and its native data binding, I have read repeatedly about the need to recode your mid level data objects to support INotifyPropertyChanged on the setters for each field in your class.
I have already coded both screen setup methods and Winforms event handlers that perform bi-directional update capability between classes and controls. Of course these would require some modification to adapt to WPF control methods and properties. I'm trying to decide whether it's worth the coding effort and ongoing maintenance required to setup INotifyPropertyChanged on each individual field that interacts with the screen, or just modify the more classic code behind event handlers. I have between 50 and 100 fields (of various types), each of which would require special coding for bi-directional binding.
Is it worth it, or am I missing something as a WPF noob?
I have many, many fields in the existing data maintenenace classes that take this form:
public class clsLot
{
// Code omitted for general error codes, enums etc.
// Here are a long list of fields which are generated by EF6 model, decorated with straightforward {get; set; }
public long idLot { get; set; }
public string LotID { get; set; }
public Nullable<long> idRecipe { get; set; }
public string PlantOrder { get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public string Inspector { get; set; }
public string LotType { get; set; }
[... Long list omitted. For ease of maintenance when new fields are added to the database and ef6 model regened, this list is copied from ef6 gened code
// maintenance methods omitted for mapping between this class and database (save, update etc.
}
When I see examples of WPF two way binding, they say the class must support INotifyPropertyChanged, and that each field must be converted
from the simpler "public string LotID {get; set;}" to something like this for each field
public class User : INotifyPropertyChanged
{
// Begin modification for each field in the class that needs to be bi-directionally mapped
private string _LotID;
public string LotID
{
get { return this._LotID; }
set
{
if(this.name != value)
{
this._LotID = value;
this.NotifyPropertyChanged("LotID");
}
}
}
// End of modification for each field
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
I have no problem with adding the public event, and the NotifyPropertyChanged method to existing classes.
My problem is the 13x expansion in the lines of code to support INotifyPropertyChanged for each field
of which I have between 50-100 fields (and can no longer be copy/pasted from autogened classes created
by Ef6 Model).
Is this worth it, vs. just moving and adjusting the existing screen setup and control event handler methods I have in the Winforms app?
The core of my problem is that I am working with autogened code that takes advantage of the "public string LotID { get; set;}" syntax, that would need to be broken down into separate private fields and public properties for each field/property that is presently autogened.
First of all, you can do the work using Find&Replace function of VS and some clever regex with one click.
Sceond of all, you forgot that you can delete all the event handlers, so in total some lines will be new, but some will be deleted.
From maintanance point of view, bindings and INPC are much more readable for humans and make it easier to solve problems like "Why this control does not show the current value?".
Can you also edit in ALL the code required to make two way sync for those properties using event handlers?
When using bindings, the xaml side is just Text="{Binding SomeStringProperty}" and it works.
** EDIT **
The main advantage is that you can use the MVVM pattern, which what WPF was designed for. That done right makes mantaining an app a lot easier, but in many cases more tedious.
I have an class which can perform many analytics on a given object and return back sets of results:
public class AnalyserClass
{
private SomeObject _someObject;
public AnalyserClass(SomeObject someobject)
{
_someObject = someobject;
}
public IEnumerable<Result> DoA
{
//checks A on someObject and returns some results
}
public IEnumerable<Result> DoB
{
//checks B on someObject and returns some results
}
//etc
}
public class Result
{
//various properties with result information
}
public class SomeObject
{
//this is the object which is analysed
}
I would like to expose these actions (DoA, DoB etc) in a CheckedListBox in a WinForm. The user would then tick the actions s/he wants performed and would then click on a Run button.
I would ideally like exposing the actions to be dynamic - so, if I develop a new action within my AnalyserClass, it will automatically show up and be executable from the WinForm without any code changes anywhere else.
I am a fairly new C# programmer. I have been researching how best to structure this and I have become a little bit confused between various patterns and which one would be most appropriate to use.
First of all I read up on the MVVM pattern, but this seems to be more complicated than is required here and I don't understand what the Model would be.
Then I looked at the Command pattern. But from what I understand, I would have to create a class wrapper for every single action (there are a lots) which would be quite time consuming and seem to be a bit cumbersome (change code in multiple places, so not 'dynamic'). I also don't understand how I could build the list of checkboxes from the command classes. This does seem to be the most appropriate pattern that I could find, but I am uncertain about it because of my lack of experience.
Your guidance is much appreciated.
I would not choose Reflection here, because it makes the things unnecessary complicated.
Furthermore, with your current approach, you would need to extend your AnalyserClass with new functionality every time you need a new analyzer tool, and that:
breaks the "open-closed" principle of SOLID,
breaks the "single responsibility" principle of SOLID,
makes your class too large and pretty unmaintainable.
I would introduce in your AnalyserClass a collection of supported actions:
class AnalyserClass
{
public IEnumerable<IAnalyzer> Analyzers { get; private set; }
}
...where the IAnalyzer interface describes your actions:
interface IAnalyzer
{
string Description { get; } // this is what user will see as the action name
Result Perform(SomeObject input);
}
Then you can implement the IAnalyzer in various classes as needed, even in different modules etc.
The only open point would be - how to add all the IAnalyzer instances into your AnalyzerClass.Analyzers collection?
Well:
you can use a DI framework (e.g. MEF) and let it discover all the things automatically,
you can inject them manually via DI,
you can use Reflection and scan the types manually,
you can add them manually e.g. in the constructor of the AnalyzerClass (simple but not recommended)
and so on...
Given a basic C# library, how do I implement functions of this library into my WPF application to handle appropriately the concepts of Binding and Commands?
I mean, need I write some own wrappers for these library classes in order to implement interfaces such as ICommand or should this be done directly in the library itself?
Some code to get my question more comprehensible:
From the library:
public class Item
{
public string Name { get; set; }
public void DoSomething() { throw new NotImplementedException; }
}
I want to implement the function DoSomething() in my XAML markup without any line of code in that .cs file since that is, from what I've read, the best practice.
(Assuming that an instance of Item is bound to the control)
<Button Command="{Binding DoSomething}"/>
Well, in order to do so, I need to implement the interface ICommand and create a command, but that is, as stated above, unclear to me since I'm using a library here.
Should I write my own Wrapper for the Item class of the API and implement the ICommand interface or is there any other way to archieve this? I've written the library by myself so changes are possible. I'm just not entirely sure about changing the library because if I do so, it is (possibly) bound to WPF.
Hi there if anything your ViewModel should handle any requests on your Model that's it's sole purpose, to get these things to work you need ICommand and if you want some more info here is link with a tutorial on RoutedCommands. If you have your Model and ViewModel defined then you can easily assign tasks to the particular Model through its VM.
P.S. I think you could treat your library as a Model and write a "wrapper" ViewModel to handle operations on it. HTH
UPDATE
Consider following:
class libClass
{
void method()
{
//do something here
}
}
code above would be your model and if you want it to be more readable you could do it this way
class libModel
{
private libClass _libClass;
public libClass LibClass { get; set; }
}
Note
You could implement INotfiyPropertyChanged in your Model to handle any changes if needed of course.
now in your VM how you use the Model
class ViewModel
{
private libModel _libModel;
public libModel LibModel { get; set; }
//after you set up your RoutedCommands
//I declare method within my VM to handle the RoutedCommands don't know
//if it works when you use Property Method
void VMMethod()
{
//use VM's property to invoke desired method from your lib
}
}
and voila! ready "wrapper" for your class with implementation in your VM.
Tip
If you want to know how to do the RoutedCommands here is a link to a tutorial.
I want to run through a series of steps that comprise a complete test. Some of these steps are automatic (so informational) and others require user interaction. Test steps are not known at compile time, they are using MEF to be loaded.
Currently I have something like
public abstract class TestRunnerBase
{
public abstract void Run();
}
With a list of steps like this:
List<TestRunnerBase> Steps = new List<TestRunnerBase>();
So all data representing a test serializable and that works okay so far. However what I really need is for a user to load a test from XML, it then walks them through the options displaying information on screen and gathering results.
But trying to work out how to create a control for data that is unknown at compile time has ended up with me getting a bit stuck on the best approach.
I am thinking to do this I would have a list of custom controls (1 a step) and the GUI would display the first step, wait for that control to be complete (I was thinking here that a raised event might work?) and then display the next if available and so on until the test is complete.
So is it possible to do this in WPF? Can you create a stack of controls in WPF that can each raise the same event to the parent container or is there a better way to do it?
But if I also use the abstract class I can't then derive a control from it also as no multiple inheritance in C# of course.
I would use MVVM and create a viewmodel that understood how to navigate the list of steps, providing a wizard type structure (prev/next) and exposing the current step.
I assume that while you have different kinds of potentially unknown steps that you have a concrete set of input options (bool, text, date, int, etc) then you could use a abstract property on your TestRunnerBase that identifies what kind of input is required (or none) using an enum that must be overriden.
Then you could use datatemplates and/or data triggers to control what is shown for each step of the test. The main viewmodel could check that conditions are right for going to the next step (perhaps a validate on your test).
Some psuedo code to get you thinking:
public enum TestInput
{
None,
Bool,
Text
}
public abstract class TestRunnerBase
{
public abstract TestInput TestInput { get; }
public bool BoolInput { get; set; }
public string TextInput { get; set; }
public abstract bool CanRun()
public abstract void Run();
}
public class MainViewModel
{
List<TestRunnerBase> Steps = new List<TestRunnerBase>();
public TestRunnerBase CurrentStep {get;set;};
public MainViewModel()
{
//loads the Steps
CurrentStep = Steps
}
public Command RunStepCommand
{
if (CurrentStep.CanRun())
{
CurrentStep.Run();
CurrentStep = Steps.Next(); //you get the idea
}
}
}
For your XAML you would bind a ContentPresenter to CurrentStep and use a datatemplate (and maybe data triggers) to control what is visible to the user (and of course bound to the UI).
In WPF you can dynamically create controls using XAML. Simply create a XAML snippet with the layout you want (either programatically or by hand) and use XamlReader.Parse to create the entire tree from the snippet. The returned object can then be inserted somewhere in the visual tree of your window.
To generate events from the visual tree generated by XamlReader you can use routed events.
When thinking of the SRP, I find that an application that I'm writing is getting out of hand for our main interface/form. I'd like to change it before we get too far into the project.
What are some techniques for making a large interface that has a "drawing surface" with toolbars, menus etc? I'd also like it to be easy for this form to be testable. Should there be other classes that know how to control the MainForm such as a ChangedStateTracker (to monitor dirty state), DocumentCreator or something along those lines to "File > New" a new document?
The problem that I'm running into is there are so many methods inside the MainForm.cs and it's really starting to get ugly to maintain.
This can be marked CW if necessary. Any other hints/tips would be greatly appreciated.
If this is an option, I would create a set of user controls that together produce the entire form.
These separate user controls can then have their own responsibility and can be tested separately.
For the logic itself, create classes.
You can create classes like CreateDocumentCommand that implement some functionality. When e.g. the new document button/menu item is clicked, create an instance of this class and execute it.
public interface ICommand
{
bool CanExecute { get; }
void Execute();
}
public class SaveDocumentCommand : ICommand
{
public bool CanExecute
{
get
{
return MainForm.Instance.CurrentDocument.IsDirty;
}
}
public void Execute()
{
// Save your document here.
}
}
This by the way is how WPF does it.
Jeremy Miller has written about this a few times - these should get you started:
http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx
http://www.jeremydmiller.com/ppatterns/default.aspx