-
-
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
Binding to events? #33
Comments
I haven't yet needed to do this in Elmish.WPF, but in vanilla MVVM you would probably get a reference to the Control's Stepping back for a second though, in your example you could just hook up a two-way binding to the |
@2sComplement Thanks! Yes, it looks like I could use SelectedItem, but I'm trying to work out whether Elmish.XamarinForms is complete enough to do everything necessary. There are a lot of events in XamarinForms that don't have a corresponding 2-way binding. |
@dsyme Ideally I try to keep code-behind limited to view-only types of interactions. I'd be curious to know what other events would be applicable here, where they would need some way of binding to the ViewModel. |
@2sComplement Some of the samples may be sloppy Xaml. Another example:
should be:
But I expect there is a lot of this kind of thing around in samples, including educational ones. Also, in the samples I'm translating I also see event hookup for
Both of these make me think that if there's some way to wire up events to commands (i.e. commands stored in the ViewModel) then it would be useful... |
<Window x:Class="Mm.HandlingEventsMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Rectangle Fill="Yellow" Stroke="Black" Width="100" Height="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</StackPanel>
</Window> Does this help for Xamarin? |
So much xaml :) We might be able to get Xamarin.Forms to allow
where the view model property I'm discussing that with the XF people as a possible Xaml extension. I think the implementation might be very simple: just allow |
@2sComplement If we use the SelectedItem bindable property we get the nasty:
The return of Have you seen this pattern before, i.e. where a change in a property on a UI element is perceived as a command as far as the application is concerned? I suppose each time this happens it's an indication of a missing Command in the UI framework, e.g. Xamarin.Forms doesn't have an ItemSelectedCommand, just the event instead. |
Lots of Xaml for sure, but it appears to be the best practice for this specific scenario. In your example, the event of interest tells you that an item was selected, so to me it makes sense to store that item in your model, and incur any side effects as a result of the selection. If you want to trigger a command from a control inside a I personally don't run in to this scenario very often; I find that, with a few exceptions, UI events that are not dependency properties are pertinent to view-side code. |
Yes, agreed. Though best practice in Xaml can also mean unusable :) In any case, the XF guys seem open to making this simpler in their variant of Xaml, either via ItemSelectedCommand or making eventing simpler as I mentioned above
Yes, that would be a fair approach |
I haven't found a good way of doing this, and the "official" approach is the |
And the |
I have just installed the |
I tried that one first, but I didn't work for me (before I gave up after one minute of trying). Maybe I did something wrong. This reminds me. I would like to add more samples, and this is one of the things for which I would like to add a sample. Then Elmish.WPF can have a completely official way to solve this problem :) |
My bad, you also have to install |
Excellent! I didn't know anything about behaviors, so I learned something new there. I put a breakpoint in Is there some way to cause |
You could use |
I added a button to hide/show the text box. I agree; it is a nice addition. The text box regains focus each time it (re)appears. PR coming soon. However, |
I am not convinced about the use of both When I build the sample in Visual Studio, I get the following build warning.
Here is the relevant section of the verbose output.
This problem persists even after I clear my NuGet cache. If I use the As of last year, it appears the correct solution is to depend on Microsoft.Xaml.Behaviors.Wpf. This blog post by Microsoft announcing the release of this NuGet package includes migration steps. I tried it, and it worked for me when adding the NuGet package dependency though Visual Studio and also building with Visual Studio. I would create a PR for this change, but I don't know how |
Thanks! Fixed in 5df8514 |
What about for binding to something like the Window.Closing event? The program has to be able to write to the event args to indicate that it doesn't want to close. |
I haven't tested, but it seems that it should be possible using the same method. Have you tried? |
I've been trying to figure out how it might be done using this mechanism. Apologies, I'm still new to Elmish.WPF, and I'm having trouble finding specific documentation. |
Hm, actually, it won't work that way because the mechanism shown above is only for sending messages to the Elmish message loop. There's no way to write to the event args. I don't have a good solution at the moment. Perhaps you could have the main window be invisible, and simply open a new window using |
For reference, here's a memoization implementation I've used. Perfect for immutable data. /// Memoizes the last return value by comparing the input using reference equality.
let memoizeOneRef (f: 'a -> 'b) =
let mutable value = ValueNone
fun x ->
match value with
| ValueSome (arg, ret) when Object.ReferenceEquals(arg, x) -> ret
| _ ->
let ret = f x
value <- ValueSome (x, ret)
ret Usage: // Original, non-memoized function
let myDomainFun x = x + 1
// Memoized version (must be declared in a stable location, i.e. not inline)
let myDomainFunMemoized = memoizeOneRef myDomainFun
// Note - do not do this, since memoizeOneRef will be applied separately
// each time it's called
// let myDomainFunMemoized x = memoizeOneRef myDomainFun x
// Use the memoized function just like you would the non-memoized one
let x = myDomainFunMemoized 2 If you need multiple parameters, either use tuples or write separate higher-arity memoization functions. Note however that memoization functions can be incorrectly used - you can pass a multi-parameter function to |
Ah ha! Thanks, that does indeed work. Goes to show how little I know about Elmish still. |
Couple thoughts...
|
@reinux Could you share some examples of how you imagine the usage to be according to your suggestions? |
For the first one:
Being able to see the model from that function right after init could be useful too, though I'm not sure if that might be too conceptually polluting. The second one:
The usage would be more or less the same as Part of the reason I'm interested in this is that |
Great suggestions! My immediate thought on having As for the |
If there's a way to bind the Of course, if In general, I think any event that has numeric parameters that need to be processed along with the model (i.e. in Will get back to you if I can think of more. |
As far as some cursory searching reveals, there is no built-in way to do this, but it might be possible to create a reusable trigger that passes the event args as command parameters. See e.g. MVVM Light's EventToCommand. A significant drawback of this method is that you'll have to do unsafe casting of the event args.
Yes, I think that would work best, because everything would be strongly typed. Your windows could surface the controls using |
Cool, will check that out :D For now, I've resorted to an unholy workaround, specifying the ID associated with a Window by passing it via a global mutable (with the assumption that Nasty, and a little precarious, but I think it'll do for now. |
@reinux can you give the |
@cmeeren Works great! Thanks for taking the time to do this.
Scratch that, not sure why I didn't notice By the way, this branch reacts slightly differently to what I think is a bug: with the latest nuget package, if you return a I've been trying to repro it with a simpler example, but I haven't been able to. With this branch, trying to do the same thing causes a null reference exception trying to access |
What a strange bug. AFAIK there should be no difference in that regard between the current nuget and the branch. Particularly since nothing in the Please let me know if you can arrive at a somewhat minimal repro, or figure out what it is. Also, may I ask what you're doing in |
Nope. Honestly, the "new" behavior is desirable, because it actually throws an exception! Will let you know if it ever comes back.
I new up an ffmediaelement element and return a Cmd.ofSub (speaking of which, I should move that to The only real question is why Elmish.WPF was silently going back to the init state, and why it stopped doing that. In fairness, this is probably one of the unforeseen consequences of having complex mutable objects in the model. This is for a separate project from when I asked about mutable state before. I'm experimenting with multiple child windows in multiple I'm probably bending Elmish way out of shape... |
Side note: Elmish contains a comment above
The alternative is to call |
Another side note: I think |
Yes, that is my guess. I have looked at the Elmish dispatch loop before and just looked at it again now. I don't see how the bug you describe could be caused by anything in Elmish (and Elmish.WPF isn't involved in this part). |
Thanks, good to know. I'm going to keep exploring for ways to clean up the model. It was easier with the other one, since I only had one instance, and I didn't have any bindings between elements. |
3.4.0 is in the pipeline and will be released shortly with the new feature. |
Okay, I think I'm getting better at this. I've managed to banish most mutable state from the model, save for For the most part, I can just pass commands in as parameters to the I guess there've always been ways around it, but the new |
Quoting #33 (comment)...
...and #33 (comment)
There is! A friend just informed me that Maybe we could expand the |
Sure, PR welcome! Though perhaps not the Window.Closing event, because the idiomatic way to handle windows is using |
Thanks @bender2k14 , good to know! |
…AndBehaviors sample elmish#33
…AndBehaviors sample elmish#33
I think everything here is resolved now. I recommend posting new issues for new problems related to events. It makes it easier to keep track of what's resolved and unresolved. |
Hi all
I'm seeing plenty of examples of Xaml where binding to events via code behind is needed, e.g. see below for a snippet of Xamarin code.
My question is - what's the right way to go about this in Elmish.WPF?
From what I've seen there doesn't seem much alternative to writing the code-behind event handler (apart from massive things like this with very intrusive Xaml) - but how would the event handler capture the Elmish dispatch routine?
Xaml:
code behind:
The text was updated successfully, but these errors were encountered: