edongashi / WpfMaterialForms

Dynamically generated forms and dialogs in WPF
MIT License
51 stars 14 forks source link

Feature suggestions and roadmap #17

Open edongashi opened 6 years ago

edongashi commented 6 years ago
redbaty commented 6 years ago

Hey, I ran into this problem recentlty and I think it's a good idea: Add a attribute to override the type builder, for example I needed a DateTimePicker but with a mask, so I had to use a ConvertField but there was no way to override it, so I manually changed it.

edongashi commented 6 years ago

Is it possible to use a mask with the calendar picker control? Do we need to modify the underlying textbox via template, or is there an easier way?

redbaty commented 6 years ago

I believe we can't use masks on calendars (Not sure tho), what I meant was something like

[Override(typeof(ConvertedField))]
public DateTime Date { get; set; }

and it would force the builder to use the specified type

edongashi commented 6 years ago

I looked at the code but this seems quite difficult, since lookup is done in a forward fashion from prop/type to builder. Forcing a specific type would require runtime checking (builders can be added or removed, this can cause unexpected states).

A simple solution would be adding a new builder for DateTime..

FormBuilder.Default.TypeBuilders[typeof(DateTime)].Insert(0, new CustomDateBuilder(...)))

where CustomDateBuilder checks some condition. If that condition matches (for example [Masked]) then return a converted field, else return null to pass.

redbaty commented 6 years ago

Hey, just leaving it here to try to make it later:

edongashi commented 6 years ago

What is the mapper stuff about? I checked the code, something like proxying objects?

redbaty commented 6 years ago

@EdonGashi Hey I was taking a look on the progress bar stuff and tough to myself: We could implement the progress button from MaterialDesignInXamlToolkit, this would be great for forms that need to do some async stuff like HTTP. Oh and I've changed this thread style and added [Password] support 🎉

edongashi commented 6 years ago

Thanks @redbaty for all the effort. The button would definitely be nice for async actions. There is also a stepper control which would be. :fire: if we could integrate that in a nice way.

An idea:

[Step("Personal details.")]
public string Name ...
public DateTime DoB...

[Step("Billing information")]
public string CardNumber ...
...
redbaty commented 6 years ago

@EdonGashi Yeah the stepper would be really nice, I think I'll try to introduce the loading button and the progress bar tomorrow and in the next days I'll take a look on how we could do the stepper thingy. But anyway this is a really great library, I should be the one thanking you! 😄

redbaty commented 6 years ago

Suggestions

[Submit] Attribute

This can be used alongside the [Field] attribute to listen to the keyup event and act as a [Action] attribute. @EdonGashi any idea how we would implement this? Is there a common presenter for fields?

edongashi commented 6 years ago

For fields such as StringField the hierarchy goes like this:

StringField : DataFormField : FormField : FormElement

DataFormField should handle Read-Write props. Regarding the views generated I'm not sure how we can extract something in common, a place to consider would be IBindingProvider, which gets bindings for fields.

I'm not quite sure I understand the meaning behind [Submit], something like dispatch an action when the field changes? Could something like [Field(OnChange=...)] work? Otherwise we can always put classic setters in properties:

public string Something
{
  get
  {
    return something;
  }
  set
  {
    something = value;
    OnSomethingChanged();
  }
}
redbaty commented 6 years ago

@EdonGashi Sorry I thought I had written it, I mean to submit this form when someone press "enter", this should work similar to the [Action] attribute

edongashi commented 6 years ago

[Action(IsDefault = true)] should trigger on enter. Could you test this quickly?

redbaty commented 6 years ago

@EdonGashi Yup just a sec

redbaty commented 6 years ago

@EdonGashi Using the following does not work.

[Action("ok", "Entrar", IsLoading = "{Binding IsLoading}", IsDefault = true)]

edongashi commented 6 years ago

Looks like this property exists in the attribute but it's not added in ActionElement. It needs to have a

public IValueProvider IsDefault { get; set; }

public IValueProvider IsCancel { get; set; }

which should be initialized from the attribute and then added to resources on Freeze(). After this the button in the template should do IsDefault={FormBinding IsDefault} and IsCancel={FormBinding IsCancel}

redbaty commented 6 years ago

@EdonGashi Hmmm, I've added it but it still won't work, am I missing something? Check it out on 40d810bf3fd4bb789b27b2acfab42fd26543db95

edongashi commented 6 years ago

Fixed, ActionAttribute didn't initialize the values. Also removed those fields from ActionElementCommand because it doesn't need them.

During a Freeze() the resources are linked to their names, which can then be accessed using {FormBinding ResourceName}