J'ai fini par supporter cela via un comportement personnalisé, dont le code est ci-dessous. Je suis plus qu'heureux de passer à une implémentation plus propre (qui ne nécessite pas d'ajouter un comportement au bouton, par exemple) si quelqu'un peut y penser.
Quelques notes sur la mise en œuvre (qui est basé sur Rx):
- Il suppose que cliquer sur le bouton d'annulation entraînera toujours dans la fenêtre fermée. Si votre bouton d'annulation peut être annulé (pour ainsi dire), le bouton ne sera pas cliqué lorsque la fenêtre est fermée.
- Si le bouton est en quelque sorte retiré de la fenêtre (dans notre cas, un contenu différent est interverti dans une région), il va dissocier le comportement.
- Tous les gestionnaires d'événements sont supprimés à la fin de la séquence, que la fenêtre ait été fermée, que le bouton ait été cliqué ou que le bouton ait été supprimé.
Et voici le code:
public class DialogCancelButtonBehavior : Behavior<Button>
{
protected override void OnAttached()
{
base.OnAttached();
Button button = AssociatedObject;
GetWindowAsync(button)
.SelectMany(window => GetWindowClosed(window))
.Where(_ => button.IsCancel)
.TakeUntil(GetButtonClicked(button))
.TakeUntil(GetButtonUnloaded(button))
.Subscribe(_ => ClickButton(button));
}
private IObservable<Window> GetWindowAsync(Button button)
{
var buttonLoaded = Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),
h => button.Loaded += h,
h => button.Loaded -= h);
return button.IsLoaded
? Observable.Return(Window.GetWindow(button))
: buttonLoaded.Take(1).Select(_ => Window.GetWindow(button));
}
private IObservable<IEvent<EventArgs>> GetWindowClosed(Window window)
{
return Observable.FromEvent<EventHandler, EventArgs>(
h => new EventHandler(h),
h => window.Closed += h,
h => window.Closed -= h);
}
private IObservable<IEvent<RoutedEventArgs>> GetButtonClicked(Button button)
{
return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),
h => button.Click += h,
h => button.Click -= h);
}
private IObservable<IEvent<RoutedEventArgs>> GetButtonUnloaded(Button button)
{
return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),
h => button.Unloaded += h,
h => button.Unloaded -= h);
}
private void ClickButton(Button button)
{
ButtonAutomationPeer peer =
(ButtonAutomationPeer)UIElementAutomationPeer.CreatePeerForElement(button);
IInvokeProvider invokeProv =
peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv.Invoke();
}
}
Le problème est que mon code qui crée le 'Window' ignore complètement le bouton, et ne peut donc pas les relier. –