2

WPF ウィンドウに単純な閉じるボタンを実装したいと考えています。ウィンドウは基本的に次のようになります。

    <Window x:Class="MyApplication.MainWindow"
            xmlns=""....
            ...."
            Title="MainWindow" WindowState="Maximized" WindowStartupLocation="CenterScreen" x:Name="mainWindow">
<DockPanel LastChildFill="True">
        <Ribbon DockPanel.Dock="Top">
            <Ribbon.ApplicationMenu>
                <RibbonApplicationMenu SmallImageSource="Resources/menu_16x16.png">
                    <RibbonApplicationMenu.FooterPaneContent>
                        <RibbonButton Label="Beenden" 
                                      Command="{Binding CmdCloseApp}" 
                                      CommandParameter="{Binding ElementName=mainWindow}"
                                      SmallImageSource="Resources/ende_16x16.png" 
                                      HorizontalAlignment="Right"/>
                    </RibbonApplicationMenu.FooterPaneContent>
                </RibbonApplicationMenu>
            </Ribbon.ApplicationMenu>
        </Ribbon>
</DockPanel>
    </Window>

このウィンドウの DataContext は、分離コードで次のインスタンスに設定されます。MainWindowViewModel

MainWindowViewModel:

public class MainWindowViewModel
{
        public ICommand CmdCloseApp { get; set; }

        public MainWindowViewModel()
        {
            CmdCloseApp = new RelayCommand<Window>(CloseApp);
        }

        public void CloseApp(Window w)
        {
            w.Close();
        }
}

In CloseAppw は常に null です。文字列パラメーターなどを使用した他のすべてのコマンドは完全に機能します-私の唯一の問題は、ウィンドウ要素を取得できず、ビューモデルへの道が見つからないことです。

ご協力いただきありがとうございます!

編集 申し訳ありませんが、単純なボタンで試してみましたが、うまくいきました-問題は次の場合にのみ発生しますRibbonButton

4

1 に答える 1

3

編集:アプリケーションメニューRibbonButtonに変更した後、Microsoft RibbonControlLibraryがポップアップメニューを使用してボタンを保持し、MainWindowがポップアップメニューのビジュアルツリーの一部(の親)ではないため、ElementNameバインディングが「 mainWindow」ウィンドウなので、null を CommandParameter に割り当てます
static Application.Current を使用して MainWindow を取得すると、機能します。
注意!MainWindow はアプリケーションのプロパティ名であり、ウィンドウの名前ではありません

<Window x:Class="WpfRelayCommandParameter.MainWindow"
    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:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
    xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
    Title="MainWindow" Height="350" Width="525"
    x:Name="mainWindow">
<DockPanel LastChildFill="True">
    <DockPanel LastChildFill="True">
        <ribbon:Ribbon DockPanel.Dock="Top">
            <ribbon:Ribbon.ApplicationMenu>
                <ribbon:RibbonApplicationMenu SmallImageSource="Resources/AppMenu.png">
                    <ribbon:RibbonApplicationMenu.FooterPaneContent>
                        <ribbon:RibbonButton Label="Beenden" 
                                  Command="{Binding CmdCloseApp}" 
                                  CommandParameter="{Binding MainWindow, Source={x:Static Application.Current}}"
                                  SmallImageSource="Resources/Exit.png" 
                                  HorizontalAlignment="Right" Click="ButtonBase_OnClick"/>
                    </ribbon:RibbonApplicationMenu.FooterPaneContent>
                </ribbon:RibbonApplicationMenu>
            </ribbon:Ribbon.ApplicationMenu>
        </ribbon:Ribbon>
    </DockPanel>
</DockPanel>

個人的には、ウィンドウへのコールバックが、ビュー モデルのニーズに合わせてカスタマイズでき、単体テストでモックできるインターフェイスを通過することを好みます。

<Window x:Class="WpfRelayCommandParameter.MainWindow"
    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:wpfRelayCommandParameter="clr-namespace:WpfRelayCommandParameter"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance wpfRelayCommandParameter:MainWindowViewModel}"
    Title="MainWindow" Height="350" Width="525"
    x:Name="mainWindow">
<Grid>
    <Button Content="Close Window" 
            Command="{Binding CmdCloseApp}" 
            VerticalAlignment="Top"
            HorizontalAlignment="Left" />
</Grid>

コード

public partial class MainWindow : Window, IMainWindow
{
    public MainWindow()
    {
        DataContext = new MainWindowViewModel(this);
        InitializeComponent();
    }
}

public interface IMainWindow
{
    void Close();
}

public class MainWindowViewModel
{
    private readonly IMainWindow _mainWindow;

    public MainWindowViewModel() : this(null)
    {
        // Design time
    }

    public MainWindowViewModel(IMainWindow mainWindow)
    {
        _mainWindow = mainWindow;
        CmdCloseApp = new RelayCommand(CloseApp);
    }

    public ICommand CmdCloseApp { get; set; }

    public void CloseApp(object parameter)
    {
        _mainWindow.Close();
    }
}

RelayCommand のCanExecute CanExecuteの type と null で発生する可能性のある問題に注意してください。

于 2016-06-24T13:11:19.923 に答える