I'm working on a Winform project. We currently have a modular design (shown in the image) in our project. Where on every user action (button clicked or selection changed etc), first we set the Model accordingly (through the controller) then the controller raises an event which is associated with a UI (View) that listens and updates them accordingly.
This flow was designed as such because whenever we need to make the whole logic of the setting/getting data to/from model and controller logic in background, it will be easily done.
For example:
Here I'm uncomfortable with the fact that while listening to an event on the UI, I need to write the code to load all user controls (like I have created a template to load 5 controls). Similarly if there may be other events in which only three controls should be loaded, there I also have to write logic to load controls.
You see, instead of loading every control independently, here I have coupled code.
I think something like dependency property (WPF) will solve this problem. But as Winform Controls are not inheriting DependencyObject
I cannot have dependency properties here (at least not as straightforward as WPF) - I have read this.
I have tried the following workaround flow, and my question is, is this approach a proper way to have a workaround for the dependency property?
- Created the
ViewModel
class, which exposes events for every user controls ofUI
. UI
does subscribe those events and updates associated controls in those events.- Created
Model
object and pass it toViewModel
, andViewModel
's object is passed inUI
.
And the flow will be like:
- When a button will be clicked, UI will
ViewModel
's theGetUserInfo()
method ViewModel
will callModel
'sGetUserInfo()
method and get actual infoViewModel
will raise events (to update UI) one by one- Thus, at the end
UI
will already be updated, and code behind will not have anything extra to do (just update UI)
Model Class:
public class UserInfoModel
{
private List<UserInfo> m_userInfoList;
public UserInfo GetUserInfo(string name)
{
//assumption: there will be only one or no user with specified name
return m_userInfoList.Where(x => x.Name == name).FirstOrDefault();
}
}
ViewModel Class:
public delegate void TextBoxUpdateHander(string textBoxText);
public delegate void RadioButtonUpdateHandler(bool radioButtonChecked);
public class UserInfoViewModel
{
#region Events Associated with UI
private event TextBoxUpdateHander TxtNameUpdatedEvent;
public event TextBoxUpdateHander TxtNameUpdatedEventAccessor
{ add { TxtNameUpdatedEvent += value; } remove { TxtNameUpdatedEvent -= value; } }
private event RadioButtonUpdateHandler RBtnMaleUpdatedEvent;
public event RadioButtonUpdateHandler RBtnMaleUpdatedEventAccessor
{ add { RBtnMaleUpdatedEvent += value; } remove { RBtnMaleUpdatedEvent -= value; } }
//**** Same way other events for other UI controls *****//
#endregion
UserInfoModel m_userInfoModel;
public UserInfoViewModel(UserInfoModel userInfoModel)
{
this.m_userInfoModel = userInfoModel;
}
public void GetUserInfoEventUpdate(string name)
{
UserInfo userInfo = this.m_userInfoModel.GetUserInfo(name);
if (userInfo != null)
{
TxtNameUpdate(userInfo.Name);
RBtnMaleUpdate(userInfo.Gender == Gender.male);
//**** Same way other methods calling to raise other events *****//
}
}
private void TxtNameUpdate(string name)
{
if (TxtNameUpdatedEvent != null)
TxtNameUpdatedEvent(name);
}
private void RBtnMaleUpdate(bool isMale)
{
if (RBtnMaleUpdatedEvent != null)
RBtnMaleUpdatedEvent(isMale);
}
//**** Same way other methods to raise other events *****//
}
UI (Form):
public partial class UserInfoView : Form
{
private UserInfoViewModel m_userInfoViewModel;
public UserInfoView(UserInfoViewModel userInfoViewModel)
{
InitializeComponent();
m_userInfoViewModel = userInfoViewModel;
EventSubScriber();
}
void m_userInfoViewModel_RBtnMaleAccessor(bool radioButtonChecked)
{
rbtnMale.Checked = radioButtonChecked;
}
void m_userInfoViewModel_TxtNameAccessor(string textBoxText)
{
txtName.Text = textBoxText;
}
//***** Same way other event handler methods ****//
private void btnFindInfoEvent_Click(object sender, EventArgs e)
{
m_userInfoViewModel.GetUserInfoEventUpdate(txtNameToFind.Text);
}
private void EventSubScriber() {/*subscribing all events*/}
private void EventUnsubscriber(){//un-subscribing all events}
}