edongashi / WpfMaterialForms

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

MaterialWindow for a class #18

Open hashitha opened 6 years ago

hashitha commented 6 years ago

Is it possible to show a window for a class like this

public class LocalSettings : INotifyPropertyChanged
    {
        private bool wiFi;
        private bool mobileData;
        private bool personalHotspot;
        private string hotspotName;
        private bool bluetooth;

        private bool facebook;
        private bool twitter;
        private bool instagram;
        private string deviceName;
        private bool sendAnonymousData;

        [Title("Settings")]

        [Heading("Connectivity", Icon = "Signal")]

        [Field(Name = "Wi-Fi", Icon = "Wifi"), Toggle]
        public bool WiFi
        {
            get => wiFi;
            set
            {
                wiFi = value;
                OnPropertyChanged();
            }
        }

        [Field(Icon = "Signal"), Toggle]
        public bool MobileData
        {
            get => mobileData;
            set
            {
                mobileData = value;
                OnPropertyChanged();
            }
        }

        [Field(Icon = "AccessPoint"), Toggle]
        public bool PersonalHotspot
        {
            get => personalHotspot;
            set
            {
                personalHotspot = value;
                OnPropertyChanged();
            }
        }

        [Field(IsVisible = "{Binding PersonalHotspot}")]
        public string HotspotName
        {
            get => hotspotName;
            set
            {
                hotspotName = value;
                OnPropertyChanged();
            }
        }

        [Field(Icon = "Bluetooth"), Toggle]
        public bool Bluetooth
        {
            get => bluetooth;
            set
            {
                bluetooth = value;
                OnPropertyChanged();
            }
        }

        [Divider]
        [Heading("Notifications", Icon = PackIconKind.MessageOutline)]

        [Field(Icon = "Twitter"), Toggle]
        public bool Twitter
        {
            get => twitter;
            set
            {
                twitter = value;
                OnPropertyChanged();
            }
        }

        [Field(Icon = "Facebook"), Toggle]
        public bool Facebook
        {
            get => facebook;
            set
            {
                facebook = value;
                OnPropertyChanged();
            }
        }

        [Field(Icon = "Instagram"), Toggle]
        public bool Instagram
        {
            get => instagram;
            set
            {
                instagram = value;
                OnPropertyChanged();
            }
        }

        [Divider]
        [Heading("Device", Icon = PackIconKind.Cellphone)]

        public string DeviceName
        {
            get => deviceName;
            set
            {
                deviceName = value;
                OnPropertyChanged();
            }
        }

        [Toggle]
        public bool SendAnonymousData
        {
            get => sendAnonymousData;
            set
            {
                sendAnonymousData = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

using something like this code

var window = new MaterialWindow(new MaterialForms.MaterialDialog(LocalSettings));
await window.Show();
redbaty commented 6 years ago

You can pass it as a content, using the new DynamicForm and passing the model in the Model property. Something like this:

var window = new MaterialWindow(new MaterialForms.MaterialDialog(LocalSettings)){Content = new DynamicForm{Model = YOURMODEL};
await window.Show();
edongashi commented 6 years ago

This definitely needs to be supported from the library. Right now the only way to show a form is to include the DynamicForm control in your xaml tree, which is a pain. The old MaterialWindow and MaterialDialog are a hardcoded mess, so it's best to stay away from them.

Because the content of the form is left abstract, there needs to be a window host and a dialog host both of which have a dynamic form as their child and some infrastructure to support it. This can be reused for any model.

Luckily, this will be quite easy, since the heavy work of generating the contents is handled by DynamicForm. All that's left to do is create two wrappers:

Window
  DynamicForm Model=Window.Model
Dialog
  DynamicForm Model=Dialog.Model

and these wrappers can be used anywhere.

The API will be really simple, I'm considering also adding some static helpers:

var mySettings = new Settings();
DynamicForm.ShowWindow(mySettings);
DynamicForm.ShowDialog(mySettings);
// Note that we don't need to wrap mySettings. DynamicForm accepts objects, types, IFormDefinitions inherently!

I have an assignment for university right now but within the next 24 hours I will add this.

Thanks @hashitha. Also thanks to @redbaty for the continuous contribution!