How to Implement IDataErrorInfo within a WPF Page (A Partial Class) - c#

It's my first experience with WPF. And I'm developing an Inventory Management System. My design model has single Window, in which a frame loads different Pages while clicking on different buttons. While adding a new Inventory into the Database, I want to ensure Data Validation. I choose IDataErrorInfo in this regard. I have to implement the interface but unable to implement just writing as public partial class AddInventoryPage : Page, IDataErrorInfo. This shows error. The signature of the class is as following
public partial class AddInventoryPage : Page
I also tried as under but unable to achieve the functionality. Even I put a breakpoint within IDataErrorInfor part but the control doesn't go there.
namespace IMS
{
public partial class AddInventoryPage : IDataErrorInfo
{
//code here
}
public partial class AddInventoryPage : Page
{
//code here
}
}
As My Inventory module is completed except Data Validation, and I'm working on the Sales module; it's not a solution to change my design model. Moreover, I'm not using any Design Pattern like MVVM. It's straight.
Looking forward to a solution.

example with a validation against the property 'Name'
public class AddInventoryPage : IDataErrorInfo
{
public string Name { get; set; }
public string Error => null;
public string this[string columnName]
{
get
{
switch(columnName)
{
case nameof(Name):
if (Name == string.Empty) return "Name can not be empty";
}
return string.Empty;
}
}
}

Related

WPF MVVM and Data Acces Layer Organisation

I have developed my first WPF applicationa (tryingt) to use MVVM. I'm still learning and would appreciate the following questions answered:
Should I keep TestReportItem class in Repository class library or move it to it's own class library?
My ViewModel does not reference a Model. It refererences the class TestReportItem. I display the TestReportItem using XAML and a datatemplate to access a string field "Title". Is this acceptable/best practice?
TestReportItem
public class TestReportItem
{
public string Title { get; set; } = string.Empty;
public string SubTitle { get; set; } = string.Empty;
public bool HasTable { get; set; }
public string Reference { get; set; } = string.Empty;
public bool HasAdditionalInformation { get; set; }
}
TestReportItemRepository
public interface ITestReportItemRepository
{
List<TestReportItem> GetAllTestReportItems();
TestReportItem GetByName(string testName);
}
XMLTestReportItemRepository
public class XMLTestReportTestStandardRepository : ITestReportItemRepository
{
private string _filePath;
public string FilePath
{
get { return _filePath; }
set { _filePath = value; }
}
public XMLTestReportTestStandardRepository(string sourceFilePath)
{
FilePath = sourceFilePath;
}
public TestReportItem GetByName(string testName)
{ ... }
public List<TestReportItem> GetAllTestReportItems()
{ ... }
MVVM is a rule of thumb and not a dogma; meaning its really flexible. Originally MVVM was based off of the three tiered data organization system. View/Business layer/DB layer. And in a sense, it is just that.
Should I keep TestReportItem class in Repository class library or move it to it's own class library?
Whether your classes reside with the main project or in an external class library is up to the design. If the design calls for reuse between different projects, then yes extract it. Otherwise being external does not add any value except in separation of work.
Remember that an external library is in a sense a different namespace to structure your code.
My ViewModel does not reference a Model. It refererences the class TestReportItem.
As to TestReportItem it is a Model. Just because it has/may have methods and operations is moot. If one needs create partial class files where the model esque properties are contained in one partial and the operations et all are in another partial are fine and one achieves separation. But that is optional
datatemplate to access a string field "Title". Is this acceptable/best practice?
Does Title get derived or generated by its being in the class. If it does, then yes, if not, place Title on the main VM and extract/build it in the getter of Title.

Accessing different Masterpages from Base Class

I have an application that uses 2 master pages. One for main pages and one for Popup pages. These both inherit from Masterpages
public partial class MainMasterPage : System.Web.UI.MasterPage
{
UserBO objUser = null;
public UserBO GetCurrentUser()
{
UserBO userBO = new UserBO();
.....
.....
return userBO;
}
}
public partial class PopupMasterPage : System.Web.UI.MasterPage
{
UserBO objUser = null;
public UserBO GetCurrentUser()
{
UserBO userBO = new UserBO();
.....
.....
return userBO;
}
}
So far so good. So my content pages all Inherit from a base class. The base class has a method that
calls the GetCurrentUser from the Base class.
public class BasePage : Page
{
//.....
protected UserBO GetCurrentUserFromMasterPage()
{
this.Master
Elsa.MasterPages.MainMasterPage master = (Elsa.MasterPages.MainMasterPage )this.Master;
return master.GetCurrentUser();
}
}
So here you can see that the base page casts the MasterPage and then calls GetCurrentUser.
Just for background... The masterpages get current user logged into the system and then draws itself using the info. If the user is in the session it gets it otherwise it loads from the database. I dont want the content pages to do the same so I wanted the base page to always get the current user for the content page from the master.
However my problem is, that because there is 2 master pages and all web pages are derived from Base
page.. I need to be able to cast to the correct master.
public partial class MyMainPage : Elsa.Pages.BasePage
{
private long _userId = -1;
public partial class MyPopupPage : Elsa.Pages.BasePage
{
private long _userId = -1;
If I put in the MasterType directive I can call the method in the content page for the correct Master.
But I dont want to call it from the content as its common method so I need it in the base.
So does anyone know how to handle this. I was thinking on deriving the BasePage again for a PopupBasePage and over writing the GetCurrentUserFromMasterPage() to cast to the popup master.
Or do I pass something into the BasePage constructor to tell it what to cast to.
I want to keep the impact to all my web pages to a minium as I have a lot of web pages.
Thanks M
You can insert an extra MasterPage as the base class for your 2 current ones:
public partial class SiteMasterPage : System.Web.UI.MasterPage
{
....
// GetCurrentUser
}
public partial class MainMasterPage : SiteMasterPage
{
....
}
public partial class PopupMasterPage : SiteMasterPage
{
}
This will allow you to implement other common features and markup (include of CSS files) in one place as well.
Does it make sense for you
using Reflection:
Master.GetType().GetMethod("GetCurrentUser").Invoke();
Do this :-
public class MasterPageBase : MasterPage
{
public PageBase PageBase { get { return (PageBase)this.Page; } }
}
public class PageBase : Page
{
// Do your Extensions Here..
}
All Pages there after Inherit from PageBase.

User Input Validation in Windows Forms Implementing Model View Presenter

I am trying to validate User Input in Windows Forms Application (using MVP design Pattern). Since this is my first project using MVP, I am not very clear where and how to put the user input validation code.
To be specific, I have a Products form which contains two text box controls, Namely ProductName and ProductPrice.
Below is the code for my ProductForm, IProductView and ProductPresenter
IProductView.cs
public interface IProductView
{
string ProductName { get; set; }
int ProductPrice { get; set; }
event EventHandler<EventArgs> Save;
}
frmProduct.cs
public partial class frmProduct : Form,IProductView
{
ProductPresenter pPresenter;
public frmProduct()
{
InitializeComponent();
pPresenter = new ProductPresenter(this);
}
public new string ProductName
{
get
{
return txtName.Text;
}
}
public int ProductPrice
{
get
{
return Convert.ToInt32(txtPrice.Text);
}
}
public event EventHandler<EventArgs> Save;
}
ProductPresenter.cs
public class ProductPresenter
{
private IProductView pView;
public ProductPresenter(IProductView View)
{
this.pView = View;
this.Initialize();
}
private void Initialize()
{
this.pView.Save += new EventHandler<EventArgs>(pView_Save);
void pView_Save(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I do want to use the ErrorProvider(EP) Control + since I would be using EP control on many forms, I would really love if I could reuse most of the code by putting the EP code in some method and passing it the controls and appropriate message. Where should I put this validation code?
Regards,
I've used a base form with the error provider on and then had other forms inherit from this. I also put the visual error code in this base form also. This meant the same code is re-used. For Mvp, you could do something similar with a base form and an interface your application views inherit from. Your presenters would then see a uniform interface for setting validation states, messages, etc.

MVP and rich user interface

I want to implement MVP pattern for my application.
MVP Passive View actually. So I came to a problem, it's easy one,
but can't decide which path should I take, so
I want to ask you guru's, how to properly work with MVP and display rich UI.
I mean, let's assume we need to display some data, and customer wants it to be TreeView.
There is requirement, that if user select different treenode, then the application updates itself with
new data or something like that.
At this point, i'm not sure how to implement View.
(All view logic goes to presenter)
I don't think that it is a good idea, to expose WinForms class
ISomeForm : IView {
//Presenter will take control of this TreeView.
TreeView Host {
get;
}
}
or exposing my data models
ISomeForm : IView {
//View knows how to display this data
List<MyDataNodes> Items {
get;
set;
}
}
or using other View interfaces.
ISomeForm : IView {
//Presenter knows what Views presenter should display.
List<IDataView> Items {
get;
set;
}
}
Any suggestions?
I would go with the View Interfaces.
In WPF MVVM, the more view separation I have, the easier it is to manage the UI/Logic interaction along the way.
I had to solve this problem using a MVC pattern. You could expose the TreeView as you suggested in your first example. Then the presenter could subscribe some events of the TreeView. But if you go this way your presenter will probably have to subscribe a lot of events of differents controls on your form. I have chosen to have a single event on the form that sends messages to the controller (in my case). The messages are represented as a class and can have any information you need. This is how my message looks:
public class MvcMessage
{
public object Source { get; private set; }
public MessageType MessageType { get; private set; }
public Type EntityType { get; private set; }
public IList InvolvedItems { get; set; }
public int NumAffected { get; set; }
public EventArgs SourceEventArgs { get; internal set; }
/// <summary>
/// Name of property who changed its value. Applies to models implementing INotifyPropertyChanged.
/// </summary>
public string PropertyName { get; set; }
public MvcMessage(object source, MessageType messageType, Type entityType)
{
this.Source = source;
this.MessageType = messageType;
this.EntityType = entityType;
}
public void Reroute(Type newEntityType)
{
MvcMessage reroutedMessage = (MvcMessage)MemberwiseClone();
reroutedMessage.EntityType = newEntityType;
Controller.NotifyAll(reroutedMessage);
}
}
... where MessageType is a enum containing a lot of common commands and requests.
My IView interface then defines the event like this:
public delegate void ViewEventHandler(MvcMessage message);
public interface IView : IViewPage, IWin32Window
{
event ViewEventHandler ViewEvent;
...
}
You should go more along the lines of the two latter examples; the view shouldn't expose WinForm-ish details to the presenter. See this answer for details on handling exactly your problem with TreeView updating - especially item 5.

Using DataAnnotations with Entity Framework

I have used the Entity Framework with VS2010 to create a simple person class with properties, firstName, lastName, and email. If I want to attach DataAnnotations like as is done in this blog post I have a small problem because my person class is dynamically generated. I could edit the dynamically generated code directly but any time I have to update my model all my validation code would get wiped out.
First instinct was to create a partial class and try to attach annotations but it complains that I'm trying to redefine the property. I'm not sure if you can make property declarations in C# like function declarations in C++. If you could that might be the answer. Here's a snippet of what I tried:
namespace PersonWeb.Models
{
public partial class Person
{
[RegularExpression(#"(\w|\.)+#(\w|\.)+", ErrorMessage = "Email is invalid")]
public string Email { get; set; }
/* ERROR: The type 'Person' already contains a definition for 'Email' */
}
}
A buddy class is more or less the direction your code snippet is journeying, except your manually coded partial Person class would have an inner class, like:
[MetadataType(typeof(Person.Metadata))]
public partial class Person {
private sealed class MetaData {
[RegularExpression(...)]
public string Email { get; set; }
}
}
Or you could have your manually partial Person class and a separate Meta class like:
[MetadataType(typeof(PersonMetaData))]
public partial class Person { }
public class PersonMetaData {
[RegularExpression(...)]
public string Email;
}
These are workarounds and having a mapped Presentation class may be more suitable.
You need to either use a metadata "buddy" class or (my preference) project onto a presentation model instead of binding views directly to entities.

Categories

Resources