Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShowDialog #1

Open
JordanMarr opened this issue Dec 9, 2019 · 9 comments
Open

ShowDialog #1

JordanMarr opened this issue Dec 9, 2019 · 9 comments

Comments

@JordanMarr
Copy link

First off, I love the idea of having a Fabulous.WPF that doesn't have the baggage of Xamarin for apps that only need to target WPF. This is very cool!

I have been doing a lot of Revit add-ins where I often need to load a window with ShowDialog. Any thoughts on how to load this way? I made a very quick attempt (without knowing what I was doing) to change WPFHost.SetRootView to call ShowDialog, but the blocking nature of the modal window caused issues (it seems to be preventing something else from initializing). The window loaded, but when I clicked a button I got "do no call dispatch during initialization"; so I am assuming that the modal window blocked initialization.

Maybe there could be a different way to run the app as a modal window.

@JordanMarr
Copy link
Author

I removed the call to "window.Show()" completely in the WPFHost SetRootView and called ShowDialog from my app. I was able to open and close the dialog multiple times from my Revit add-in -- (obviously no BSOD issues as I was having with Xamarin). So that makes this library viable for use with Revit add-in development!

So then it comes down to getting more WPF controls ported over to the Fabulous.WPF.View module.
The xaml page that I wanted to try to create first requires the DockPanel, RadioButton, Border and DataGrid (or at least something comparable to a grid).

@TimLariviere
Copy link
Member

Oh great! Fabulous expects a single root by default. But if you found a way that suits you that's awesome. :)

So then it comes down to getting more WPF controls ported over to the Fabulous.WPF.View module.
The xaml page that I wanted to try to create first requires the DockPanel, RadioButton, Border and DataGrid (or at least something comparable to a grid).

For that, you will need to run the generator project with the following arguments

-m src\Fabulous.WPF\WPF.json -o src\Fabulous.WPF\WPF.fs -d

Once you do that, a file called 1-assembly-types.json will contain all the information that Fabulous.CodeGen found in the WPF dlls.
If the controls are in there, you can add to src\Fabulous.WPF\WPF.json:

{
  "type": "System.Windows.Controls.Border",
  "properties": [

  ]
},

This will make the generator generates a wrapper for Border without any property.
To add a property, change it to:

{
  "type": "System.Windows.Controls.Border",
  "properties": [
    {
        "source": "CornerRadius"
    }
  ]
},

After compiling everything, you will be able to use it:

View.Border(
    cornerRadius = System.Windows.CornerRadius(15)
)

This a mostly trial-and-error process.
Don't hesitate to look at the console output of the generator. It will report anything wrong.
Also, files like 1-assembly-types.json will give an insight into what's going on inside Fabulous.CodeGen.

@TimLariviere
Copy link
Member

Also, there are quite a few values you can override in src\Fabulous.WPF\WPF.json, if need be.
https://github.com/fsprojects/Fabulous/blob/master/Fabulous.CodeGen/src/Fabulous.CodeGen/Models.fs

@JordanMarr
Copy link
Author

The View.Border is generating, and I can assign properties.
The problem is that I'm trying to add the "Child" property, which is of type UIElement, but it won't let me assign a TextbBlock to it:

View.Border(
   child = View.TextBlock(text = "asdf"),
   borderBrush = Brushes.Red
)

Property metadata:

{
            "type": "System.Windows.Controls.Border",
            "properties": [
                {
                    "source": null,
                    "name": "Child",
                    "inputType": "System.Windows.UIElement",
                    "defaultValue": "null"
                },
                {
                    "source": "CornerRadius",
                    "defaultValue": "System.Windows.CornerRadius(0.)"
                },
                {
                    "source": "BorderThickness",
                    "defaultValue": "System.Windows.Thickness(0.)"
                },
                {
                    "source": "Padding",
                    "defaultValue": "System.Windows.Thickness(0.)"
                },
                {
                    "source": "BorderBrush",
                    "defaultValue": "null"
                },
                {
                    "source": "Background",
                    "inputType": "System.Windows.Media.Brush",
                    "defaultValue": "null"
                }
            ]
        }

@TimLariviere
Copy link
Member

TimLariviere commented Dec 13, 2019

Could you try to declare System.Windows.UIElement (with CanBeInstantiated = false) in the JSON file? (no property required)

When a type is declared, the Generator automatically replaces the type (when required by a property) by ViewElement (which allows using child = View.TextBlock() instead of child = new System.Windows.Controls.TextBlock()).

@JordanMarr
Copy link
Author

It worked!

I had to put UIElement above FrameworkElement though or else the generated code was in the wrong order.

@JordanMarr
Copy link
Author

I am unsurprisingly stuck on the DockPanel.Dock attached property. I don't know how it would be possible for child elements to display attached properties in their c'tors; it seems like a more reasonable approach might be for View.DockPanel c'tor to have "childrenTop", "childrenLeft", "childrenRight" and "childrenLeft" lists in addition to "children". Then anything in "childrenTop", for example, could be added to the DockPanel's Dock dependency property.

@JordanMarr
Copy link
Author

On second thought, the "LastChildFill" property requires there be one list. Maybe Children could be a list of a Dock discriminated union:

type DockDirection =
  | Top of ViewElement
  | Left of ViewElement
  | Right of ViewElement
  | Bottom of ViewElement

Then DockPanel Children could be a DockDirection list.

@JordanMarr
Copy link
Author

Sorry, I should have looked at what already exists in Fabulous for attached properties (Grid / .GridRow method)!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants