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

[SelectedItem] Has anyone successfully made rec subModelSelectedItem work using either *dynamic* or *static* bindings? #620

Closed
YkTru opened this issue Dec 11, 2024 · 12 comments

Comments

@YkTru
Copy link

YkTru commented Dec 11, 2024

[Problem]: Has anyone fully successfully used subModelSelectedItem with a recursive data structure in any ways using the ElmishWPF API, without encountering issues with the WPF SelectedItem property, and if you can share that code please (ideally not too hacky)?

[Context]: there are numerous issues with WPF's SelectedItem, which I experienced too using recursive structure (eg: model updates, but not the UI).

[Solutions]: More specifically, I want to confirm if it is even feasible to implement this using either dynamic or static bindings or any alternative approaches (e.g., twoWayOpt or other safe/FP-idiomatic techniques that I might not have considered).


[Limitations]: If not, it risks failing to support very common desktop application use cases (e.g., file and folder trees, master-detail views with nested items, etc.).

383334375-84530b38-7472-4b56-98fc-3b79e32592b5

or

wpf-treeview-devexpress

Thank you

@YkTru YkTru changed the title [SelectedItem] Has anyone successfully made *rec subModelSelectedItem* work using *either dynamic or static bindings*? [SelectedItem] Has anyone successfully made rec subModelSelectedItem work using either *dynamic* or *static* bindings? Dec 11, 2024
@YkTru
Copy link
Author

YkTru commented Dec 12, 2024

[Documentation]: I insist: If its indeed a limitation - either with dynamic or static bindings - it must be clearly communicated upfront (ie in the docs) to ElmishWPF API users to prevent them from wasting time and effort, potentially falling into the same rabbit hole I am stucked in for months now, and associated anxiety (which, in my case, is quite significant now).

That said, months later, I still hold out hope that it can work (though I acknowledge I may be influenced by a sunk cost fallacy bias). if you
can share any working solution/code sample this will help tremendously for sure
.


@marner2 - I know I ask you a lot of questions but all I need is a little direction for rec subModelSelectedItem as you did in this post which helped me tremendously; maybe I misinterpreted as an encouragement to get more involved, I apologize if that's not the case:

I appreciate the feedback. At this point, the more feedback I have once I restart effort on it in the next few months, the more efficiently I'll be able to work.

Thank you

@awaynemd - I know that you’ve faced similar/identical challenges regarding multi-level subModelSelectedItem, and that you might have felt as desperate as I do now. However, you had the privilege/chance of seeking help during the "ElmishWPF Community Golden Era," when support was more readily available. I’d really like to know if you managed to get it working and, if possible, whether you could share a small code sample. I’d truly appreciate it. Thank you very much

@TysonMN -I’m sorry for repeatedly asking the same question (and please don’t misunderstand me—I really hate being that "pain in the ass" guy..), but despite going over and over again through all the old ElmishWPF issues/PR history related to rec subModelSelectedItem, it’s still unclear to me whether you have a working solution using ElmishWPF dynamic bindings.At this point, a code sample would be worth a thousand words. Thank you

@TysonMN
Copy link
Member

TysonMN commented Dec 12, 2024

it’s still unclear to me whether you have a working solution using ElmishWPF dynamic bindings.

@YkTru, come on. If I knew how to do this, then I would tell you.

@TysonMN
Copy link
Member

TysonMN commented Dec 12, 2024

Quoting #619 (comment)

I can open an issue + MRE this week showing different bugs - for dynamic and static bindings

Please share a git repository containing feature branches with your various attempts. Also clearly describe what doesn't work or what you don't like. You can include static attempts, but I will only be considering the dynamic attempts.

@YkTru
Copy link
Author

YkTru commented Dec 16, 2024

it’s still unclear to me whether you have a working solution using ElmishWPF dynamic bindings.

@YkTru, come on. If I knew how to do this, then I would tell you.

I apologize; I thought perhaps you knew but either didn’t have the time to write a full example, didn’t remember the exact details (most of the discussions on this topic in "Issues/PR" are from 2020), or it might have been private code from your previous work at the company.

That said, I think I’ve made some progress, although certain aspects feel hacky and less than ideal (note: some of the code was generated by GPT-o1 (mostly in the TreeviewSelectedItemBehavior)).

but I will only be considering the dynamic attempts.

Here is the repository containing only a dynamic attempt (which is not too different from my earlier static attempts so I can build from it I guess)

If you find the code difficult to read or follow, I'll take time to rewrite/refactor it just let me know.

@YkTru
Copy link
Author

YkTru commented Dec 16, 2024

Video_2024-12-17_004322.mp4

[What I think works]:

  • TreeView SelectedItem: I added a custom TreeViewSelectedItemBehavior (WPF Behavior) to enable SelectedItem-like functionality on the TreeView. (I intentionally avoided using SelectedPath/Value/Index.)

  • Elmish.Cmd: This feels like a hack to me. To ensure that the moved item is reselected (at least in the model; more on this below), I had to use Cmd.OfMsg SelectItem. I attempted to rely solely on the selectItem helper, as suggested by Zaid Ajaj in ElmishBook, but this didn’t work (at least the when I tried).

[Issues]:

  • UI Deselection: In the video, you’ll notice that when I click or select an item, the background turns blue. However, after repeatedly pressing MoveUp on Level > 0 (ie works only at the root level), while the data source updates correctly, the UI loses the Focus/SelectedItem visual state (i.e., the blue background disappears), which is visually confusing.

-ListView Deselection: I added a ListView for SelectedItem comparison so I can bind to out-of-box ListView's SelectedItem but I get same deslection issues; so the UI visual bug might not come from the custom behavior I've added to the TreeView, but the Model or worst, WPF. (I thought it might be an HashCode issue, but why would the ItemsSource + property editor updates immediately on different selection?)

  • Weird Logs at Initialization: When the application initializes, I see frequent InitializeBindings and TryGetMember messages in the logs (you’ll notice this if you run it) which clearly is not right.

  • MoveUp/Down Error: I get this error along the way when I press MoveUp/Down on Level > 0:
    [Error] ["main"] TryGetMember FAILED: Failed to find an element of the SubModelSeq binding "TopChildren" with ID "7971582a-606e-48c9-9ae2-f8daf35151e7" in the getter for the binding "SelectedItem", I'm not sure why since the model and UI-ItemsSource updates as expected.

  • TreeView FocusedItem: I (kind of desperately) introduced a FocusedItem field in the model (which feels unnecessary and noisy) + attempted to use it in the behavior to directly update UI focus. I also tried integrating it directly with MoveUp/MoveDown logic, but it didn’t seem to improve the situation and added unnecessary complexity.

As an additional note, I’d like to point out that this related ElmishWPF sample) exhibits a similar deselection issue. In fact, it performs even worse—the MoveUp/MoveDown functionality simply toggles the item in place:

Video_2024-12-16_051905.mp4

Well, I hope you’ll be able to help. Thanks a lot

@YkTru
Copy link
Author

YkTru commented Dec 16, 2024

In fact, I get this XAML Binding Failures as soon I select any item, even though the selection functionality seems to work thanks only to the behavior I guess:

Severity	Count	Data Context	Binding Path	Target	Target Type	Description	File	Line	Project
Error	1	DynamicViewModel`2	SelectedItem	TreeViewSelectedItemBehavior.SelectedItem	Object	Failed to get value. InvalidOperationException:'System.InvalidOperationException: Property path is not valid. 'System.Dynamic.DynamicObject+MetaDynamic' does not have a public property named 'Items'.	B:\Projects\Elmish\learning\SubModelSelectedItem_MRE\MRE.WPF\MainWindow.xaml	75	MRE.WPF

Debug:
2024-12-16 17:50:20 [Error] ["main"] TryGetMember FAILED: Failed to find an element of the SubModelSeq binding "TopChildren" with ID "338fbfef-094b-43b6-9305-9d20db32250a" in the getter for the binding "SelectedItem"


For these reasons, I feel the xaml behavior approach might be hacky too, or at least not properly implemented.

@YkTru
Copy link
Author

YkTru commented Dec 17, 2024

Update: I have opened an issue on the WPF GitHub repository as for the weird UI-deselection behaviors: dotnet/wpf#10182.

But the runtime logs seems to tell there is a problem with my ElmishWPF code anyway.

@TysonMN Do you have suggestions on how to debug this? (There might be an issue with how I wrote the bindings; I have very little experience with dynamic bindings, so it's difficult for me to determine. Thanks)

@TysonMN
Copy link
Member

TysonMN commented Dec 17, 2024

For the WPF issue, in addition to including the code directly in the issue, also include a GitHub repo with that code and any other code needed to immediately reproduce the behavior in the video. You want to make it as easy as possible for others to help you.

Do you have suggestions on how to debug this?

Yes. As with all bugs, try to create a minimal reproduction.

Do you think your reproduction is minimal?

There might be an issue with how I wrote the bindings; I have very little experience with dynamic bindings, so it's difficult for me to determine.

I am a bit confused by this question. It makes me think that the production you shared in the WPF issue depends on Elmish.WPF, but I didn't see any Emlish.WPF, and it would be bad/wrong to include such code in the reproduction.

So to clarify, is there any Elmish.WPF code in that example?

@YkTru
Copy link
Author

YkTru commented Dec 17, 2024

Do you think your reproduction is minimal?

The "successfully made (...) work" part of my title is of course vague, since - as I'm sure you already know/have experienced - many thing can go wrong using the dreaded WPF SelectedItem (here is another specific example).

Here’s what I believe is the minimal requirement (and what I started with):

  • A Tree/recursive data structure
  • A subModelSelectedItem binding
  • WPF: A TreeView and a way to bind to its SelectedItem property. For unclear—and frankly frustrating—reasons, this property doesn't exist on the TreeView control. As a result, it must be implemented manually. (In this case, I chose to use a Behavior. If the goal were to keep it minimal, I should not. However, nothing can be selected to demonstrate the issue, obviously.)

I created a branch that (I believe) respects only the minimal requirements. I kept the mock and the ListView so you can observe what happens in the log when selecting any 'item on Level > 0'. However, ultimately, the TreeView with a SelectedItem property is more appropriate, convenient, and relevant for representing selection within a recursive data structure.


For the record: what I added during my investigation (repo), which I agree is not "minimal":

  • A ListView, which has a built-in SelectedItem property. I included this to demonstrate that the selection issues occur on items beyond Level 0, just like with the TreeView.
  • A TextBlock UI log and a TextBox property editor. These provide quick visual feedback (instead of relying on the noisy Console/Debug log) to confirm that the Model is updating the SelectedItem field and TreeView's ItemsSource correctly at all times, even though the TreeView's SelectedItem (or perhaps FocusedItem?) does not behave as expected on Level > 0.
  • A FocusedItem field to test if it's a WPF "Focus" issue (not a SelectedItem), which I have removed in my latest commit.
  • buildMockTree: Used to simulate a specific, concrete scenario.
  • *MoveUp/Down: While the selection appears to work fine when clicking or using arrow keys, this addition highlights a bug with SelectedItem at Level 0. I could have demonstrated this with other functionality (e.g., removing an item and attempting to select the previous one if it exists).
  • Cmd.ofMsg: I haven't found another way to enforce re-selection.

@YkTru
Copy link
Author

YkTru commented Dec 17, 2024

There might be an issue with how I wrote the bindings; I have very little experience with dynamic bindings, so it's difficult for me to determine.

I am a bit confused by this question. It makes me think that the production you shared in the WPF issue depends on Elmish.WPF, but I didn't see any Emlish.WPF, and it would be bad/wrong to include such code in the reproduction.

So to clarify, is there any Elmish.WPF code in that example?

The fact is I can't currently determine whether the issue lies with Elmish.WPF's subModelSelectedItem, WPF itself (such as the ListView's SelectedItem or the custom SelectedItem behavior I implemented for the TreeView), or even my model/update logic.

Initially, I didn't include the full repository in the 'WPF GitHub issue' because I understand that most people aren't familiar with or don't encourage using F# with WPF. From my experience, this often leads to responses like "Why don't you just use C# + MVVM?" or "can't help: written in F#". I wanted to keep the focus on the TreeView and the custom SelectedItem behavior I created so yes, I didnt want to include ElmishWPF code on the 'WPF Github'. Though I followed your advice and added the full repo.

@TysonMN
Copy link
Member

TysonMN commented Dec 18, 2024

I can't currently determine whether the issue lies with Elmish.WPF's subModelSelectedItem, WPF itself (such as the ListView's SelectedItem or the custom SelectedItem behavior I implemented for the TreeView), or even my model/update logic.

Then you shouldn't have created an issue in the WPF repo.

@YkTru
Copy link
Author

YkTru commented Dec 19, 2024

(closed: will a open a more focused issue on dynamic bindings)

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