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

Binding.twoWay instead of subModelSelectedItem #395

Open
Evangelink opened this issue Jul 2, 2021 · 8 comments
Open

Binding.twoWay instead of subModelSelectedItem #395

Evangelink opened this issue Jul 2, 2021 · 8 comments

Comments

@Evangelink
Copy link
Contributor

Hi there,

I am trying to replace the various use of Binding.subModelSelectedItem in my code with Binding.twoWay but I am failing to understand how to do so properly.

Solution 1:

  • Replace SelectedItem by SelectedValue in the binding of my view.
  • Replace Binding.subModelSelectedItem with Binding.twoWay.

When I run I hit:

Cannot save value from target back to source. BindingExpression:Path=SelectedKeyFrame; DataItem='ViewModel`2' (HashCode=12937084); target element is 'ListBox' (Name=''); target property is 'SelectedValue' (type 'Object') InvalidCastException:'System.InvalidCastException: Unable to cast object of type 'Elmish.WPF.ViewModel`2[System.Object,System.Object]' to type 'Microsoft.FSharp.Core.FSharpOption`1[System.String]'.

Solution 2:

  • Replace SelectedItem by SelectedValue in the binding of my view.
  • Move the binding as a child of the Binding.subModelSeq
  • Replace Binding.subModelSelectedItem with Binding.twoWay and fix the types.

When I run the code I hit:

Cannot get 'SelectedKeyFrame' value (type 'Object') from '' (type 'ViewModel`2'). BindingExpression:Path=SelectedKeyFrame; DataItem='ViewModel`2' (HashCode=12937084); target element is 'ListBox' (Name=''); target property is 'SelectedValue' (type 'Object') InvalidOperationException:'System.InvalidOperationException: Property path is not valid. 'System.Dynamic.DynamicObject+MetaDynamic' does not have a public property named 'Items'.

What I am missing?

@TysonMN
Copy link
Member

TysonMN commented Jul 3, 2021

I am trying to replace the various use of Binding.subModelSelectedItem in my code with Binding.twoWay.

Why?

I am failing to understand how to do so properly.
...
Replace SelectedItem by SelectedValue in the binding of my view.
...
What I am missing?

What you are trying to do is not possible. For each element in a SubModelSeq binding, Elmish.WPF creates an instance of ViewModel<_, _>. This instance is the value corresponding to the property SelectedValue. You don't have the ability to read such an instance, and you don't have access to a different instance (used in the SubModelSeq binding) that you could set.

For this reason, the SubModelSelectedItem binding was created. It maps between this private type and the ID of your items in the SubModelSeq binding.

@Evangelink
Copy link
Contributor Author

I am trying to replace the various use of Binding.subModelSelectedItem in my code with Binding.twoWay.

Why?

The doc states "Only use this if you are unable to use some kind of SelectedValue or SelectedIndex property with a normal twoway binding.", which I understood as there is a simpler/better way through SelectedValue but I am unable to make it work hence this ticket :)

From your reply, I am assuming that's not bad to use this binding kind and I am trying to do a pointless refactoring. Out of curiosity, how am I supposed to correctly use the SelectedValue (I couldn't see an example. or I missed it)?

@TysonMN
Copy link
Member

TysonMN commented Jul 5, 2021

Ah, yes. I understand now. The documentation can be made clearer here. Thanks for the ticket.

It is not possible to use a TwoWay binding on SelectedValue when the corresponding ItemSource is bound with a SubModelSeq binding. Instead, the ItemSource would need to be bound with a OneWaySeq binding.

It is possible to bind to SelectedIndex via a TwoWay binding for both OneWaySeq and SubModelSeq bindings.

I think it is ok to use a
SubModelSelectedItem binding when the corresponding ItemSource is bound with a SubModelSeq binding. The main reason to not use a SubModelSelectedItem binding is that it is less type safe than other bindings.

@Evangelink
Copy link
Contributor Author

As usual thanks for the clear explanations @TysonMN!

@Evangelink
Copy link
Contributor Author

@TysonMN I am trying to find a way to improve the doc comment and in the process I am actually wondering if I got things right.

When do you recommend to use subModelSeq vs oneWaySeq? Maybe I am not doing things "the right way". Basically I am now wondering if we should be using subModelSeq "only" when we want to split the code to have another Model object and otherwise use oneWaySeq?

@TysonMN
Copy link
Member

TysonMN commented Jul 19, 2021

A OneWaySeq binding can be thought of as an optimized version of a SubModelSeq binding (the keyed version now that we also have an unkeyed version). In a SubModelSeq binding, the type of each instance in the sequence given to WPF is Elmish.WPF's internal ViewModel<_, _> type. That type is not used in a OneWaySeq binding. Instead, elements given to Elmish.WPF by thy user's function are the same elements given by Elmish.WPF to WPF.

You are reminding me that I want to extract "sequencing" as a composable effect. I will spend time thinking about that. I have been making lots of progress lately, so hopefully I have an update on this soon.

@TysonMN
Copy link
Member

TysonMN commented Jul 22, 2021

I am going to create a Selection sample to clarify this.

@TysonMN
Copy link
Member

TysonMN commented Jul 22, 2021

I just added a Capabilities sample with just a single screen for Selection so far. There is a simple SelectedIndex example and a complex SelectedValue example.

@Evangelink, is there a selection scenario that is still confusing to you? If so, then I will resolve that by adding another selection example. If not, then I will close this issue.

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