Question

I'm using the MVVM pattern so my view-model doesn't know anything about the view, and the view is displayed via DataTemplates.

When the view isn't displayed anymore, I want to take a screenshot of it (with a utility class). So I want to bind to FrameworkElement.Unloaded, and when its hit, take a screenshot of the usercontrol for use in another control to select which view to go to.

I read this article, which makes it appear as if attached properties would work (I'm using it on the UserControl object) http://blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.html

I get the error that a binding can only be set on a DependencyObject or DependencyProperty. I followed his instructions properly. Any idea why this isnt working or how I can bind to that in a MVVM scenario?

Is it not possible to bind to that particular event or to an event in the root xaml node?

Here's teh code (in addition to the EventBehaviorFactory in the link above)

public static class FrameworkElementBehavior
{
    public static readonly DependencyProperty UnloadedCommandProperty = EventBehaviourFactory.CreateCommandExecutionEventBehaviour(FrameworkElement.UnloadedEvent, "UnloadedCommand", typeof(FrameworkElementBehavior));

    public static void SetUnloadedCommand(DependencyObject o, ICommand value)
    {
        o.SetValue(UnloadedCommandProperty, value);
    }

    public static ICommand GetUnloadedCommand(DependencyObject o)
    {
        return o.GetValue(UnloadedCommandProperty) as ICommand;
    }
}


    <UserControl x:Class="WTF.BuxComp.Prism.Modules.Win.OrderEntryPos.Views.CustomerView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WTF.BuxComp.Prism.Modules.Win.OrderEntryPos.Helpers"
                 mc:Ignorable="d" 
                 d:DesignHeight="510" d:DesignWidth="716" 
local:FrameworkElementBehavior.UnloadedCommand="{Binding UnloadedCommand}">

and the exact error is

A 'Binding' cannot be set on the 'SetUnloadedCommand' property of type 'CustomerView'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Was it helpful?

Solution

The best thing I can suggest is to map to a regular event handler then call OutOfViewCommand.Execute from within your control to your DataContext. You will also need to map UserControl.DataContextChanged on your control and save your datacontext locally.

public partial class MainWindow : Window
{
    private object Data { get; set; }

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        this.Data = e.NewValue;
    }

    private void Window_Unloaded(object sender, RoutedEventArgs e)
    {
        if(this.Data != null)
             this.Data.OutOfViewCommand.Execute(null);
    }
}

XAML:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" DataContextChanged="Window_DataContextChanged" FrameworkElement.Unloaded="Window_Unloaded">
<Grid>

</Grid>

Though this does not strictly conform with MVVM, a compromise you will often face with framework calls, it still works in a re-usable way with any view model.

OTHER TIPS

For this you may need to correctly name your attached proerty.... its name declared is OutOfViewCommand but it should be UnloadedCommand

 public static class FrameworkElementBehavior
 {
    public static readonly DependencyProperty UnloadedCommandProperty =
         EventBehaviourFactory.CreateCommandExecutionEventBehaviour
           (FrameworkElement.UnloadedEvent,
            "UnloadedCommand",
            typeof(FrameworkElementBehavior));

    public static void SetUnloadedCommand
      (DependencyObject o, ICommand value)
    {  
       o.SetValue(UnloadedCommandProperty, value);
    }

    public static ICommand GetUnloadedCommand
      (DependencyObject o)
    {
      return o.GetValue(UnloadedCommandProperty) as ICommand;
    }
} 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top