locked
MVVM - Bind event - Interactivity RRS feed

  • Question

  • I've downloaded the Interactivity DLL via nuget and try now to bind an event of a ReportViewer.

    My xaml looks like this:

    <Window
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
        <Grid>
            <WindowsFormsHost>
                <rv:ReportViewer>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Load">
                            <i:InvokeCommandAction Command="{Binding LoadReport}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </rv:ReportViewer>
            </WindowsFormsHost>
        </Grid>
    </Window>

    This does not seem to work, as it already marks it in xaml with the message:
    The attached property "Triggers" can only be applied to types that are derived from "DependencyObject".

    How can I bind the Load event correctly to "LoadReport" ?

    public ICommand LoadReport
    {
        //get...
    }

    Tuesday, August 16, 2016 7:14 AM

Answers

  • The error message should be pretty self-explanatory. You can only apply an interaction trigger to a DependencyObject and WindowsFormHost is not a DependencyObject. A Windows Forms control has no concept of XAML. It draws the child Windows Forms control in a separate HWND that is always on top of the WPF elements. Please refer to the following page for more information: http://www.abhishekshukla.com/wpf/advanced-wpf-part-5-of-5-interop-in-windows-presentation-foundation/

     


    But you don't really need to apply an interaction trigger to be able to invoke the command. Interaction triggers is a XAML thing but you might as well handle an event, such as for example the ChildChanged event, for the WindowsFormsHost and invoke your command from the code-behind of the view, e.g.:

    <WindowsFormsHost ChildChanged="WindowsFormsHost_ChildChanged">
                ...
            </WindowsFormsHost>

    private void WindowsFormsHost_ChildChanged(object sender, System.Windows.Forms.Integration.ChildChangedEventArgs e)
            {
                System.Windows.Forms.Integration.WindowsFormsHost host = sender as System.Windows.Forms.Integration.WindowsFormsHost;
                if(host.Child != null)
                {
                    YourViewModel vm = this.DataContext as YourViewModel;
                    if(vm != null)
                    {
                        vm.LoadReport.Execute(null);
                    }
                }
            }

    This does not break the MVVM pattern as you are still just invoking the command of the view model from the view. MVVM is mainly about separation of concerns. It is not about eliminating code-behind and trying to everything in XAML. After all, XAML is a markup language and not nowhere near as much expressive and concise as a programming language as C#. While it may be possible to create an entire complex view in pure XAML without writing any C# code, it is not always a good thing to do so when it comes to maintainability and code readiness. And in this case you don't really have a choice unless you write your own custom interaction trigger that may be applied to FrameworkElements as well.


    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Marked as answer by DotNet Wang Wednesday, August 31, 2016 2:22 AM
    Tuesday, August 16, 2016 5:42 PM