2 votes

Les CommandBindings WPF définis dans une fenêtre ne sont pas disponibles dans une autre fenêtre

J'ai ce problème où j'ai toutes ces CommandBindings définies dans la MainWindow, et ces commandes sont disponibles dans cette fenêtre pour être utilisées dans n'importe quel bouton ou élément de menu. Le problème est que si dans d'autres fenêtres la liaison de commande n'est pas disponible (elle est toujours fausse), même si le propriétaire de la nouvelle fenêtre est la MainWindow.

Vous pouvez voir le problème ici.

Toute aide est la bienvenue.

Voici le code.

XAML MainWindow :

<Window x:Class="ContextMenuDialogProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ContextMenuDialogProblem"
        Title="MainWindow" Height="350" Width="525"
        FocusManager.FocusedElement="{Binding RelativeSource={x:Static RelativeSource.Self}, Mode=OneTime}">
    <Window.CommandBindings>
        <CommandBinding Command="local:LocalCommandManager.ShowDialogCommand" CanExecute="CanExecuteShowDialogCommand" Executed="ShowDialogCommandExecuted" />
    </Window.CommandBindings>
    <Window.ContextMenu>
        <ContextMenu>
            <MenuItem Command="local:LocalCommandManager.ShowDialogCommand" />
        </ContextMenu>
    </Window.ContextMenu>
    <Grid Background="Red">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Button Grid.Row="0"
                Content="Open SubWindow"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Padding="6"
                Click="Button_Click" />
        <Button Grid.Row="1"
                Content="Show Dialog Command Test"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Padding="6"
                Command="local:LocalCommandManager.ShowDialogCommand" />
    </Grid>
</Window>

CS MainWindow :

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void CanExecuteShowDialogCommand(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void ShowDialogCommandExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("Show Dialog");   
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Window wnd = new SubWindow() { Owner = this };
        wnd.Show();
    }
}

CS LocalCommandManager :

public static class LocalCommandManager
{
    private static object syncRoot = new object();

    private static RoutedUICommand _showDialogCommand;
    public static RoutedUICommand ShowDialogCommand
    {
        get
        {
            lock (syncRoot)
            {
                if (_showDialogCommand == null)
                    _showDialogCommand = new RoutedUICommand("Show Dialog", "ShowDialogCommand", typeof(LocalCommandManager));
                return _showDialogCommand;
            }
        }
    }
}

Sous-fenêtre XAML :

<Window x:Class="ContextMenuDialogProblem.SubWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:local="clr-namespace:ContextMenuDialogProblem"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SubWindow" Height="300" Width="300">
    <Grid>
        <Button Command="local:LocalCommandManager.ShowDialogCommand" Content="Show Dialog" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="6" />
    </Grid>
</Window>

3voto

Thomas Levesque Points 141081

Le champ d'application de la CommandBindings est limitée à l'élément où elle est définie, ce comportement est donc parfaitement normal. Vous devez ajouter l'élément CommandBinding a SubWindow si vous voulez l'utiliser à cet endroit.

1voto

ARSolog Points 11
<StackPanel Background="Transparent">
    <StackPanel.ContextMenu>
        <ContextMenu ItemsSource="{Binding Path=AnotherWindow.CommandBindings}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Path=Command.Name}" />
                    <Setter Property="Command">
                        <Setter.Value>
                            <MultiBinding Converter="{StaticResource commandConverter}">
                                <Binding />
                                <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}}" />
                            </MultiBinding>

public class CommandConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var cb = value[0] as CommandBinding;
        var cm = value[1] as ContextMenu;

        if(cb == null || cm == null)
            return null;

        cm.CommandBindings.Add(cb);
        return cb.Command;
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

fonctionne bien sur .net 4.0

1voto

Guido Mocha Points 544

Si vous voulez ajouter une commande pour tous les Windows, c'est la solution :

    public partial class App : Application
    {
        public App()
        {
            var binding = new CommandBinding(MyCommands.DoSomethingCommand, DoSomething, CanDoSomething);

            // Register CommandBinding for all windows.
            CommandManager.RegisterClassCommandBinding(typeof(Window), binding);
        }

        private void DoSomething(object sender, ExecutedRoutedEventArgs e)
        {
            ...
        }

        private void CanDoSomething(object sender, CanExecuteRoutedEventArgs e)
        {
            ...
            e.CanExecute = true;
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X