-
-
Notifications
You must be signed in to change notification settings - Fork 71
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
Attempting to emulate C# CollectionViewSource among three views of the same list. #300
Comments
It might be two weeks before I have time to look into this.
Do you know how to do this in C#? |
@TysonMN Yes. I'm updating the repo with most of it working. Each usercontrol correctly works to display its specific filter to the xaml's. The obvious errors I see are:
In any event, I'll keep trying. Happy Thanksgiving! New Code at: https://github.com/awaynemd/PatientFinder |
Both C# and F# have access to the .NET API, so this can probably be done the same in both languages. |
@TysonMN I think I got the DateTime thing working, now to get messages from the children up to the parent?? |
The parent needs to match on the child's message. Module Parent
type ParentModel =
{ Child: ChildModel }
type ParentMsg =
| ChildMsg of ChildMsg
let update msg m =
match msg with
| ChildMsg MessageForParent -> // child is telling me something
| ChildMsg msg -> { m with Child = Child.update msg m.Child } |
@TysonMN Do I need to add MessageForParent to the Msg du of the parent? (I'm getting the error: "This rule will never be matched"). Thanks.
|
Order matters. let update msg m =
match msg with
| ChildMsg MessageForParent -> // child is telling me something
| ChildMsg msg -> { m with Child = Child.update msg m.Child } is not the same as let update msg m =
match msg with
| ChildMsg msg -> { m with Child = Child.update msg m.Child }
| ChildMsg MessageForParent -> // child is telling me something // warning: This rule will never be matched |
@TysonMN Changing the order now results in: | FinderLastNameMsg msg -> "This rule will never be matched"??? |
You need to match in this order | FinderLastNameMsg SetText -> ...
| FinderLastNameMsg msg -> ... Here is what the match expression documentation says.
You are misunderstanding the use of "in turn" there. |
@tyson :( Parent module:
The first one yields: Uppercase variable identifiers should not generally be used in patterns, The second yields: This rule will never be matched I'm hopeless...I guess I'll just eat worms. |
The only branch in your repo is
You are your own worst enemy. You need to be your biggest fan and most enthusiastic cheerleader.
|
@TysonMN Yes/No. Everything works as is--but everything is independent, i.e. Each list/submodel works to correctly filter only on what the user types into the TextBox for that list. However, what I would like to achieve is have the three lists all share a common itemsSource with a filter that is the logical "And" of each/all the inputs from each lists textBox. Hence, I'm thinking I need someway for the topmost "App" model to send the source list (the one before filtering) along with the combined filter to each submodel which can then modify its part of the filter, while each submodel will send its filter back to the main model so the other children/lists will have it. Anyway, long story short, I want the submodels to send the text received from their TextBox back up to the main model--and I don't know even where to start (so there is no code for it...yet). Thanks for the encouragement. F# and Elmish/Elmish.WPF are great frameworks--but there is a very steep learning curve. |
I can look at your overall design and desired behavior eventually. In the meantime, I can help you with the match expression that was either giving you an error or a warning if you share it with me. |
@TysonMN I find the discussion here most pertinent to what I am looking for: https://discourse.elm-lang.org/t/modifying-parent-state-from-child-page-in-an-elm-spa-example-like-architecture/2437 But how to apply this to Elmish.wpf is (temporarily) above my pay grade. How is Elmish.WPF related to Elm? (p.s., I think I got all my match expressions working--except those as mentioned in the article). |
I recently reached the point in my application at work where it is now common for me to write new code in which a child updates the state of its parent. I don't know what is best. As mentioned in that discussion, this is what I am doing.
|
@TysonMN Please take a look at: https://tarmil.fr/article/2019/12/17/elmish-page-model This is a good article that pretty well describes my problem. It will take awhile for me to understand it :) |
That is a nice article. I currently use the second approach, which involves a discriminated union. As mentioned in the article, it is better than the first approach with a bunch of
I also like this discussion. I like the idea of having an
Elmish implements the Elm / Model-View-Update / MVU architecture in F#. Elmish.WPF is a specialization of Elmish to WPF and with the pragmatic decision to have the user statically define their WPF UI just like in a traditional WPF application instead of dynamically generating this content like in Elm and many other UI-specific implementations of the Elm architecture. |
@TysonMN I'm still trying to understand this code. It works well to transmit the child text back up to the parent. (This was taken from a really good blog: https://medium.com/@MangelMaxime/my-tips-for-working-with-elmish-ab8d193d52fd )
|
Ah, yes. Thanks for finding and sharing that. I remember reading this post by Mangel when I was new to Elmish.WPF, and I remember that he had a suggestion on how to do child-to-parent communication, but I didn't remember what he suggested. I now see (in the language of the Elm discussion) that he recommends an OutMsg type but not the full translator pattern. |
@TysonMN I have made significant progress with this and would like to share, but I do not want to destroy the main repo here represented. How do I do that? |
Make a branch and push that to your repo. |
@TysonMN The newest version, posted below, has most of the behavior I need. It works correctly to:
What I don't like:
Lastly the ONLY way I could achieve child-to-parent communication was to use Program.mkProgramWpf. I could never get I'd appreciate any suggestions to improve this code--especially a way to avoid multiple copies (although with different sorts) of the same list. I have 20,000 names. Thanks Please review updated version at: https://github.com/awaynemd/PatientFinder |
Glad to hear that you have made progress. I should be able to review in detail within one week. |
@TysonMN :-) !! |
lol, what? Did you solve all your problems? 👀 |
I executed your program, but it crashes on load because I don't have your connected service. After I replaced let data = context.GetAllPatientNamesAsync()
return! Async.AwaitTask data with return Array.empty the application doesn't crash, but then I don't have any data, and it doesn't seem like I can add any. What would you like help with now? |
@TysonMN Sorry...I do not know how to include database material in a github example. I wish I could say I've solved all my problems :) Now, I seemed to have done something which prevents me from exiting the program! Or its in some kind of loop?? I'll continue to work on it. Thanks. |
If you seed it with some fake data, then I will take a look. |
I am now reporting back. I love the translator pattern! The thing I liked the least about the Elmish.WPF/src/Samples/SubModelSeq/Program.fs Lines 231 to 236 in 8e8d3b0
Syntactically, it is unsatisfying to have the wildcard pattern in a match. Semantically, this function is admitting that a mistake was made because having both those IDs the same at two different levels is definitely wrong. I "knew" why this was happening. It is because those three messages are meant for the parent while the other two are meant for the child. Elmish.WPF/src/Samples/SubModelSeq/Program.fs Lines 154 to 159 in 8e8d3b0
| CounterMsg of CounterMsg // change MY counter
| AddChild // add a child to ME
| Remove of Guid // remove CHILD with that ID...don't remove ME
| MoveUp of Guid // move up CHILD with that ID....don't move ME up
| MoveDown of Guid // move down CHILD with that ID...don't move ME down ...but I was creating those last three messages like they should applied to "ME" and then fixing my mistake via The idea that I didn't have, the idea present in both this post by Maxime Mangel Now let me differentiate the approaches by Maxime and Alex as I understand them in the context of Elmish.WPF. I will call the approach by Maxime the "OutMsg pattern" and I will call the approach by Alex the "OutMsg with translator pattern". As the names suggest (and as I just said in the previous paragraph), both approaches introduce a second message type called the out message. In the OutMsg pattern, the conversation from an out message to the parent message happens in For examples of the OutMsg with translator pattern applied to Elmish.WPF, see the The advantage of the OutMsg approach is that it is immediately applicable to all implementations of the Elm architecture. As I understand the OutMsg with translator pattern for Elmish.WPF, the place to apply that translation is in the And to add another plug for @cmeeren, what do you think? What do you think about achieving child-to-parent communication via the OutMsg with translator pattern? What do you think about the application of that pattern to the Now to go apply the OutMsg with translator pattern in my application at work. |
I think the translator pattern is as ingenious as it is simple. 😊 It improves the SubModelSeq sample, though since it is recursive and makes use of several generic wrapper types, it's so complicated already that it's not the best way to demonstrate it (not even for me, who is at least somewhat familiar with the sample). |
Completely agree. I had partially written a new sample called To simplify things, I think we could rename the |
Yes, that might be a good idea. We should remember to search the whole repo for "SubModelSeq" and update any references in documentation etc. |
@TysonMN Sorry to be so dense here. I've been following this excellent conversation. When you get a chance, can you explain to this newbie the English meaning of: | BranchMsg (pId, LeafMsg (Remove cId)) when pId = cId -> LeafMsg (Remove cId) What does it accomplish? Thanks. |
Are you asking for its semantic meaning or its syntactic meaning? It doesn't have a good semantic meaning. It is a hack I found to get the correct behavior. Otherwise, messages were either causing changes in the wrong place or not causing any change at all. Syntactically, it is a case in a pattern match. Not only must the target match that structure, but it must also satisfy the predicate |
Closed due to lack of activity. Feel free to continue the conversation. |
How to emulate the C# CollectionView functionality.
I have attempted (unsuccesfully) to do the following:
download a list of names (i.e., ViewName) from a WCF service. This works! (Although I do not know if my use of Async is correct not to block the UI). But for now, this does work correctly to download about 20,000 names.
Create only ONE read of the database.
The read database names are then to be provided to three separate user controls. Each user control is to receive user input from a textbox and will be sorted in a different order. Each user control will then provide this user input into a shared filter. Shared in the sense that all three usercontrols will use the same filter on the same list of objects. The filters are:
1. All ViewNames with LastName starting with the text characters received from the LastName usercontrol.
2. All ViewNames with FirstName starting with the text character received from the FirstName usercontrol.
3. All ViewNames with BirthDate equaling the date typed into the BirthDate usercontrol.
The final filter which ALL LIST VIEWS will use in the boolean combination of the three above conditions.
(The sorted viewables will be:
Everything initially worked individually, but I was unable to use the filter from one usercontrol in another. That is, my thinking is to have one source list/array and somehow pass the conditions of each usercontrol to the other usercontrols --or top module. Hence, althought the sort orders for the list will be different, the source list and the filter will be identical between all user controls.
I tried passing a common record, "names", with the Msg component--but failed miserably.
If anybody could give any thought to this, this newbie would sure appreciate it!
(As an aside, I never could figure out how to verify a text string as a valid date in F# to be used in a birth date filter :( )
TIA
Full (frustrating) code found at: https://github.com/awaynemd/PatientFinder
The text was updated successfully, but these errors were encountered: