Best practice with Winforms that are externally updated - winforms

I am wondering whether it is a good idea to make labels public so other classes can change them and get their value. Is this a good idea? If not, how should it be done then?

I wouldn't make the label public.
It would be better to add a public method that was specific to what the label was displaying, and have it update the label.
For example, if your label was a "System status" label, you might want to add (to your Form/UserControl):
public void SetStatusInformation(string currentStatus)
{
this.statusLabel.Text = currentStatus;
}
This allows you, later, to change how this information is displayed (in case you want to use a different control), and also simplifies your API, since the public methods are very clear to the user.

it's a bad idea. WinForms leaves many "what's the best way to do X?" questions open; and your best answer is to follow established patterns and practices (which aren't WinForms specific).
Read up on the MVP or MVC patterns. They are both high-level patterns which focus on seperating out your UI-specific code from your business-logic. Without this seperation your application can quickly become a maintenance nightmare, and things that should be simple get much more complicated.
For your specific scenario you would likely end up with a Model (your business-logic) which uses databinding to show it's data on the WinForms screen. When a change on the UI occurs it would be the Model that receives the change, and that change would propagate to the UI via databinding.

I would suggest wrapping in a setter property or method because it's very possible you'll have to do something like add logging or re-call on window's main thread if the caller is from another one. I found it easier to just always use code like the following when exposing functionality that lets clients update anything graphical.
public void SetStart()
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate()
{
this.SetStart();
});
}
else
{
progressBar1.Value = 0;
progressBar1.Visible = true;
}
}

Related

Deprecation of TableRegistry::get()

I'd like to ask what are your thought on deprecation of the TableRegistry::get() static call in CakePHP 3.6?
In my opinion it was not a good idea.
First of all, using LocatorAwareTrait is wrong on many levels. Most important, using traits in such way can break the Single Responsibility and Separation of Concerns principles. In addition some developers don't want to use traits as all because they thing that it breaks the object oriented design pattern. They prefer delegation.
I prefer to use delegation as well with combination of flyweight/singleton approach. I know that the delegation is encapsulated by the LocatorAwareTrait but the only problem is that it exposes the (get/set)TableLocator methods that can be used incorrectly.
In other words if i have following facade:
class Fruits {
use \Cake\ORM\Locator\LocatorAwareTrait;
public function getApples() { ... }
public function getOranges() { ... }
...
}
$fruits = new Fruits();
I don't want to be able to call $fruits->getTableLocator()->get('table') outside of the scope of Fruits.
The other thing you need to consider when you make such changes is the adaptation of the framework. Doing TableRegistry::getTableLocator()->get('table') every time i need to access the model is not the best thing if i have multiple modules in my application that move beyond simple layered architecture.
Having flyweight/singleton class like TableRegistry with property get to access desired model just makes the development more straight forward and life easier.
Ideally, i would just like to call TR::get('table'), although that breaks the Cake's coding standards. (I've created that wrapper for myself anyways to make my app bullet proof from any similar changes)
What are your thoughts?

Winforms, how to update the UI without injecting UI dependencies?

Consider the following text book example class:
class Worker
{
public void SomeUpdateMethod(SomeObject input)
{
// Some long running process, candidate for a multi-threaded operation
}
}
Since Worker class knows nothing about the UI, it can be considered reusable.
However: Once we want to update the UI - Now the Business Object (in this case Worker class) - Needs to be aware of the UI elements it needs to update. This might be a label or progress bar.
It seems like an anti pattern. And breaks a clean layer (Business Logic and Presentation) structure.
How has this problem been solved - a small example or just the high level theory will do - thank you.
Events and Delegates are the way to do this.

Do I have too many WPF layers here?

I think I'm on my way to finally grokking MVVM. I was just looking at a situation I found myself in and I'm wondering if I should combine two of my layers. I currently have a structure like this:
Domain models (in a separate .net project)
WPF-side "models" which wrap domain models and track dirty state
WPF ViewModels
Views
The question is whether I should combine 2 and 3. Right now #2 is the layer that gets passed around by my mediator to facilitate all the viewmodels knowing what document is currently opened. But I think my code for 2 and 3 is too similar and is unnecessary duplication at this point.
Example:
// in layer 2, class ProjectDocument
// Project is an instance of the domain model
public string Name
{
get { return Project.Name; }
set
{
if (Project.Name == value) return;
Project.Name = value;
Dirty = true;
}
}
// in layer 3, class ProjectSettingsViewModel
// _project is a ProjectDocument
public string Name
{
get { return _project.Name; }
set
{
_project.Name = value;
OnPropertyChanged("Name");
}
}
Seeing that struck me as unnecessary. So should I combine them? On one hand, it would remove a lot of redundant code and I'd have fewer places to update when I change things. On the other, I might be giving one class too much responsibility, and also it seems inappropriate for an actual ViewModel to be passed around to other VMs via my mediator. The ProjectSettingsViewModel wouldn't use even half of the fields on ProjectDocument if they were combined.
Maybe I'm looking at this the wrong way. Is there a better way to reduce the duplication while still keeping the responsibilities separate?
I have a master viewmodel that handles application states like which document/tab/window is open and I have an ISettingssService for other global needs. Passing one viewmodel to another is discouraged and you might want to think about creating am iSettings service that can be injected into the viewmodels, then the viewmodels can interact with "global" settings but the viewmodels are still decoupled because they do not depend on another viewmodel.
So, I would not combine them. Either I would have a dictionary of documents that can be open in the master viewmodel with a current open doc property or move this logic to a service/interface that gets used by each viewmodel.
Hope this helps.

Is ReactiveUI Production Ready?

I've been looking into the feasability of using Reactive UI in production code. Some of the features are really appealing, but I have concerns about taking a dependency on this library. These include:
Whacky naming and conventions. For example, protected members starting with lower case, and the RaiseAndSetIfChanged method depends on your private member beginning with an underscore. I understand Paul Betts (ReactiveUI author) has a Ruby background, so I guess that's where the odd naming stems from. However, this will cause a real issue for me, since standard naming (as per Stylecop) is enforced throughout my project. Even if it wasn't enforced, I'd be concerned by the resultant inconsistency in naming that this will cause.
Lack of documentation/samples. There is some documentation and a lonely sample. However, the documentation is just a series of (old) blog posts and the sample is based on V2 of the library (it's now on V4).
Odd design, in parts. For example, logging is abstracted so as not to take a dependency on a specific logging framework. Fair enough. However, since I use log4net (and not NLog) I will need my own adapter. I think that will require me to implement IRxUIFullLogger, which has a metric crapload of methods in it (well over 50). I would have thought a far better approach would be to define a very simple interface and then provide extension methods within ReactiveUI to facilitate all the requisite overloads. In addition, there's this weird IWantsToRegisterStuff interface that the NLog assembly depends on, that I won't be able to depend on (because it's an internal interface). I'm hoping I don't need that...
Anyway, my concern here is the overall design of the library. Has anyone been bitten by this?
I'm already using MVVM Light extensively. I know Paul did a blog post where he explains you can technically use both, but my concern is more around maintainability. I suspect it would be horribly confusing having both intermingled in one's code base.
Does anyone have hands-on experience with using Reactive UI in production? If so, are you able to allay or address any of my above concerns?
Let's go through your concerns piece by piece:
#1. "Whacky naming and conventions."
Now that ReactiveUI 4.1+ has CallerMemberName, you don't have to use the conventions at all (and even then, you can override them via RxApp.GetFieldNameForPropertyFunc). Just write a property as:
int iCanNameThisWhateverIWant;
public int SomeProperty {
get { return iCanNameThisWhateverIWant; }
set { this.RaiseAndSetIfChanged(ref iCanNameThisWhateverIWant, value); }
}
#2. Lack of documentation/samples
This is legit, but here's some more docs / samples:
http://docs.reactiveui.net/ (this is the official ReactiveUI documentation, a work in progress but definitely where you want to start)
https://github.com/reactiveui/ReactiveUI.Samples
https://github.com/reactiveui/RxUI_QCon
https://github.com/play/play-windows
#3. "I would have thought a far better approach would be to define a very simple interface and then provide extension methods within ReactiveUI to facilitate all the requisite overloads"
Implement IRxUILogger instead, it has a scant two methods :) ReactiveUI will fill in the rest. IRxUIFullLogger is only there if you need it.
"In addition, there's this weird IWantsToRegisterStuff interface "
You don't need to know about this :) This is only for dealing with ReactiveUI initializing itself so that you don't have to have boilerplate code.
"I suspect it would be horribly confusing having both intermingled in one's code base."
Not really. Just think of it as "MVVM Light with SuperPowers".
I am answering as someone who has used ReactiveUI in a few production systems, has had issues with the way RxUI does stuff, and has submitted patches to try and fix issues I've had.
Disclaimer: I don't use all the features of RxUI. The reason being I don't agree with the way those features have been implemented. I'll detail my changes as I go.
Naming. I thought this was odd too. This ended up being one of the features I don't really use. I use PropertyChanged.Fody to weave in the change notification using AOP. As a result my properties look like auto properties.
Doco. Yes there could be more. Especially with the newer parts like routing. This possibly is a reason why I don't use all of RxUI.
Logging. I've had issues with this in the past. See pull request 69. At the end of the day I see RxUI as a very opinionated framework. If you don't agree with that opinion you can suggest changes, but that's all. Opinionated does not make it bad.
I use RxUI with Caliburn Micro. CM handles View-ViewModel location and binding, Screen and Conductors. I don't use CM's convention binding. RxUI handles Commands, and ViewModel INPC code, and allows me to react to property changes using Reactive instead of the traditional approaches. By keeping these things separate I find it much easier to mix the two together.
Does any of these issues have anything to do with being production ready? Nope. ReactiveUI is stable, has a decently sized user base, problems get solved quickly in the google group and Paul is receptive to discussion.
I use it in production and so far RxUI has been perfectly stable. The application has had problems with stability, some to do with EMS, others with an UnhandledException handler that was causing more problems than it was solving, but I've not had any problems with the ReactiveUI part of the application. However, I have had issues regarding the ObservableForProperty not firing at all, which I may have used incorrectly and did work consistently (incorrectly) in my test code as well as in the UI at run time.
-1. Paul explains that the _Upper is due to using reflection to get at the private field in your class. You can either use a block such as below to deal with the StyleCop and Resharper messages, which is easy to generate (from the Resharper SmartTag)
/// <summary>The xxx view model.</summary>
public class XXXViewModel : ReactiveObject
{
#pragma warning disable 0649
// ReSharper disable InconsistentNaming
[SuppressMessage("StyleCop.CSharp.NamingRules",
"SA1306:FieldNamesMustBeginWithLowerCaseLetter",
Justification = "Reviewed. ReactiveUI field.")]
private readonly bool _IsRunning;
[SuppressMessage("StyleCop.CSharp.NamingRules",
"SA1306:FieldNamesMustBeginWithLowerCaseLetter",
Justification = "Reviewed. ReactiveUI field.")]
private string _Name;
....
or change your properties from the full
/// <summary>Gets or sets a value indicating whether is selected.</summary>
public bool IsSelected
{
get { return _IsSelected; }
set { this.RaiseAndSetIfChanged(x => x.IsSelected, value); }
}
to its component parts such as
/// <summary>Gets or sets a value indicating whether is selected.</summary>
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
this.RaisePropertyChanging(x => x.IsSelected);
_isSelected = value;
this.RaisPropertyChanged(x=>x.IsSelected);
}
}
}
This pattern is also useful where you don't actually supply a "simple" property accessor, but may require a more derived variant where setting one value affects multiple others.
-2. Yes the documentation isn't ideal but I found that after Rx, picking up the RxUI samples was quite easy. I also note that the jumps from 2->4 seem to have all come with the changes to support Windows 8/Windows 8 Phone, and having picked up ReactiveUI for a Windows Store App then the DotNet 4.5 support is excellent. i.e. use of [CallerName] now means that you simply this.RaiseAndSetIFChanged(value) no need for the expression.
-3. I haven't any feedback on the logging side as I've not elected to use it.
-4. I've not mixed and matched with others frameworks either.
There's also a list of other contributors to ReactiveUI 4.2 at http://blog.paulbetts.org/index.php/2012/12/16/reactiveui-4-2-is-released/, including Phil Haack.

Entity Framework: Context in WPF versus ASP.Net... how to handle

Currently for ASP.Net stuff I use a request model where a context is created per request (Only when needed) and is disposed of at the end of that request. I've found this to be a good balance between not having to do the old Using per query model and not having a context around forever. Now the problem is that in WPF, I don't know of anything that could be used like the request model. Right now it looks like its to keep the same context forever (Which can be a nightmare) or go back to the annoying Using per query model that is a huge pain. I haven't seen a good answer on this yet.
My first thought was to have an Open and Close (Or whatever name) situation where the top level method being called (Say an event handling method like Something_Click) would "open" the context and "close" it at the end. Since I don't have anything on the UI project aware of the context (All queries are contained in methods on partial classes that "extend" the generated entity classes effectively creating a pseudo layer between the entities and the UI), this seems like it would make the entity layer dependent on the UI layer.
Really at a loss since I'm not hugely familiar with state programming.
Addition:
I've read up on using threads, but the
problem I have with a context just
sitting around is error and recovery.
Say I have a form that updates user
information and there's an error. The
user form will now display the changes
to the user object in the context
which is good since it makes a better
user experience not to have to retype
all the changes.
Now what if the user decides to go to
another form. Those changes are still
in the context. At this point I'm
stuck with either an incorrect User
object in the context or I have to get
the UI to tell the Context to reset
that user. I suppose that's not
horrible (A reload method on the user
class?) but I don't know if that
really solves the issue.
Have you thought about trying a unit of work? I had a similar issue where I essentially needed to be able to open and close a context without exposing my EF context. I think we're using different architectures (I'm using an IoC container and repository layer), so I have to cut up this code a bit to show it to you. I hope it helps.
First, when it comes to that "Something_Click" method, I'd have code that looked something like:
using (var unitOfWork = container.Resolve<IUnitOfWork>){
// do a bunch of stuff to multiple repositories,
// all which will share the same context from the unit of work
if (isError == false)
unitOfWork.Commit();
}
In each of my repositories, I'd have to check to see if I was in a unit of work. If I was, I'd use the unit of work's context. If not, I'd have to instantiate my own context. So in each repository, I'd have code that went something like:
if (UnitOfWork.Current != null)
{
return UnitOfWork.Current.ObjectContext;
}
else
{
return container.Resolve<Entities>();
}
So what about that UnitOfWork? Not much there. I had to cut out some comments and code, so don't take this class as working completely, but... here you go:
public class UnitOfWork : IUnitOfWork
{
private static LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("UnitOfWork");
private Entities entities;
public UnitOfWork(Entities entities)
{
this.entities = entities;
Thread.SetData(slot, this);
}
public Entities ObjectContext
{
get
{
return this.Entities;
}
}
public static IUnitOfWork Current
{
get { return (UnitOfWork)Thread.GetData(slot); }
}
public void Commit()
{
this.Entities.SaveChanges();
}
public void Dispose()
{
entities.Dispose();
Thread.SetData(slot, null);
}
}
It might take some work to factor this into your solution, but this might be an option.

Resources