WPF Привязка ICommand к событию (FrameworkElement.Unloaded)

Я использую шаблон MVVM, поэтому моя модель представления ничего не знает о представлении, а представление отображается через DataTemplates.

Когда представление больше не отображается, я хочу сделать его снимок экрана (с служебным классом). Итак, я хочу привязаться к FrameworkElement.Unloaded, и при его попадании сделать снимок экрана пользовательского элемента управления для использования в другом элементе управления, чтобы выбрать, в какое представление перейти.

Я прочитал эту статью, из-за которой создается впечатление, что прикрепленные свойства будут работать (я использую его для объекта UserControl) http://blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.html

Я получаю сообщение об ошибке, что привязку можно установить только для DependencyObject или DependencyProperty. Я правильно выполнил его инструкции. Любая идея, почему это не работает или как я могу привязаться к этому в сценарии MVVM?

Невозможно привязать к этому конкретному событию или к событию в корневом узле xaml?

Вот код (в дополнение к EventBehaviorFactory по ссылке выше)

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}">

и точная ошибка

«Привязка» не может быть установлена ​​для свойства «SetUnloadedCommand» типа «CustomerView». «Привязка» может быть установлена ​​только для DependencyProperty объекта DependencyObject.


person Chris Klepeis    schedule 06.06.2012    source источник


Ответы (2)


Лучшее, что я могу предложить, - это сопоставить с обычным обработчиком событий, а затем вызвать OutOfViewCommand.Execute из вашего элемента управления в свой DataContext. Вам также потребуется сопоставить UserControl.DataContextChanged с вашим элементом управления и сохранить ваш текст данных локально.

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.

person jimmyjambles    schedule 06.06.2012
comment
Для еще более общего решения вы можете заменить this.Data.OutOfViewCommand.Execute (null) на (DataBinder.Eval (this.Data, OutOfViewCommand) как ICommand) .Execute (null) - person jimmyjambles; 07.06.2012
comment
Это дало мне 90% решения, спасибо! Единственная небольшая корректировка, которую мне пришлось сделать, это if (e.NewValue is ViewModel vm) this.Data = vm;, поскольку событие DataContextChanged срабатывает перед событием Unloaded, возвращая this.Data к null, если его не избежать. - person Pseudonymous; 22.01.2020

Для этого вам может потребоваться правильно назвать свой присоединенный объект .... его объявленное имя OutOfViewCommand, но оно должно быть 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;
    }
} 
person WPF-it    schedule 07.06.2012
comment
Кажется, это устранило ошибку времени выполнения, но команда не выполняется. - person Chris Klepeis; 07.06.2012