【问题标题】:C#/WPF How to make close application button from a ViewModelC#/WPF 如何从 ViewModel 制作关闭应用程序按钮
【发布时间】:2021-07-03 03:39:38
【问题描述】:

所以我对整个 C#/WPF 事物还是陌生的,并且想知道如何制作一个按钮,单击该按钮将关闭应用程序。 我尝试了许多来自谷歌搜索的建议,例如:

这些似乎都不能正确地帮助我。下面我提供了我目前拥有的代码,这些代码是我按照 ViewModel 导航教程制作的。如果需要更多代码,请告诉我。

文件: File List

MainMenuViewModel:

using Creator.Commands;
using Creator.Stores;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace Creator.ViewModels
{
    class MainMenuViewModel : ViewModelBase
    {
        public ICommand NavigateItemCreateMenuCommand { get; }

        public MainMenuViewModel(NavigationStore navigationStore)
        {
            NavigateItemCreateMenuCommand = new NavigateCommand<ItemCreateMenuViewModel>(navigationStore, () => new ItemCreateMenuViewModel(navigationStore));
        }
    }
}

MainMenuView:退出按钮必须关闭应用程序

<UserControl x:Class="Creator.Views.MainMenuView"
             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:Creator.Views"
             mc:Ignorable="d" 
             d:DesignHeight="720" d:DesignWidth="1280">
    <Grid Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <DockPanel Background="LightBlue" Grid.Row="1" Grid.Column="1" >
            <StackPanel>
                <Label Content="Main Menu" HorizontalAlignment="Center" VerticalAlignment="Stretch" FontWeight="Bold" FontFamily="Century Gothic" FontSize="24"/>
                <Button Content="Create Item" FontWeight="Bold" FontFamily="Century Gothic" FontSize="18" Margin="20,0,20,5" Padding="0,5,0,5" Command="{Binding NavigateItemCreateMenuCommand}"/>
                <Button Content="Quit" FontWeight="Bold" FontFamily="Century Gothic" FontSize="18" Margin="20,0,20,5" Padding="0,5,0,5" VerticalAlignment="Bottom"/>
            </StackPanel>
        </DockPanel>
    </Grid>
</UserControl>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Creator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

TL;DR: 我需要在 MainMenuViewModel/MainMenuView 上设置 Quit 按钮来关闭应用程序。

【问题讨论】:

  • 不太清楚你想要什么。按钮关闭应用程序或只是一个窗口。你写MainMenuView,但不是Window,而是UserControl。如果是应用程序,则只需使用命令扩展您的 VM,您可以在其中调用 Application.Current.Shutdown();
  • @Rekshino 是的对不起,我的意思是应用程序,认为窗口和应用程序关闭是相同的。会更新。
  • 这里提供的解决方案是可行的方法:stackoverflow.com/a/16182065/3873053
  • 这能回答你的问题吗? Close Window from ViewModel

标签: c# wpf mvvm


【解决方案1】:

使用 QuitCommand 扩展您的 ViewModel 并将其绑定到 Button

class MainMenuViewModel : ViewModelBase
{
    public ICommand NavigateItemCreateMenuCommand { get; }
    public ICommand QuitCommand { get; }

    public MainMenuViewModel(NavigationStore navigationStore)
    {
        NavigateItemCreateMenuCommand = new NavigateCommand<ItemCreateMenuViewModel>(navigationStore, () => new ItemCreateMenuViewModel(navigationStore));
        
        QuitCommand = new RelayCommand((par) => { Application.Current.Shutdown(); });
    }
}

<Button Content="Quit" FontWeight="Bold" FontFamily="Century Gothic" FontSize="18" Margin="20,0,20,5" Padding="0,5,0,5" VerticalAlignment="Bottom" Command="{Binding QuitCommand}"/>

Why RelayCommand 中找到RelayCommand 的实现

【讨论】:

  • 谢谢,这真的很有帮助:)
【解决方案2】:

您应该使用 Command 关闭 ViewModel 中正在运行的窗口。 您可以通过将父控件Window 交给CommandParameter来导入当前运行的MainWindow

我使用 MVVM 为您制作了一个示例。 希望对你有帮助。
?Github

结构

MainMenuView.xaml

<Grid>
    <Grid Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <DockPanel Style="{StaticResource MAIN.DOCK}">
            <StackPanel>
                <Label Style="{StaticResource MAIN.LABEL}"/>
                <Button Style="{StaticResource BTN.CREATE}"/>
                <Button Style="{StaticResource BTN.QUIT}"/>
            </StackPanel>
        </DockPanel>
    </Grid>
</Grid>

MainMenuView.xaml.cs

public partial class MainMenuView : UserControl
{
    public MainMenuView()
    {
        InitializeComponent();
        DataContext = new MainMenuViewModel();
    }
}

MainMenuViewModel

public class MainMenuViewModel
{
    public ICommand QuitCommand { get; set; }

    public MainMenuViewModel()
    { 
        QuitCommand = new RelayCommand<object>(QuitApp);
    }

    private void QuitApp(object obj)
    {
        if (obj is Window window)
        {
            window.Close();
        }
    }
}

MainMenuResource

整个资源来源在 Github。

<Style TargetType="{x:Type Button}" x:Key="BTN.QUIT">
    <Setter Property="Command" Value="{Binding QuitCommand}"/>
    <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
    <Setter Property="Content" Value="Quit"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="FontFamily" Value="Century Gothic"/>
    <Setter Property="FontSize" Value="18"/>
    <Setter Property="Margin" Value="20 0 20 5"/>
    <Setter Property="Padding" Value="0 5 0 5"/>
    <Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>

【讨论】:

  • 这是关闭窗口,而不是关闭应用程序,如果您同时打开了其他shell,您会遇到问题。
  • window.Close() 我认为这是一个好方法。默认情况下,当您在要关闭的 Window 对象上调用 Close() 时,Closing 和 Closed 等事件也会按顺序工作。
【解决方案3】:

首先我将创建一个界面

public interface IClosable
{
  Action Close { get;set; }
}

那么你的viewmodel应该实现这个接口

MainWindowViewModel : ICloseable
{
 public Action Close { get;set; }
 //your code 
}

然后在窗户上

public partial class MainMenuView : Window
{
    public MainMenuView()
    {
        InitializeComponent();
        DataContext = new MainMenuViewModel();
           
        if(DataContext is IClosable closable)
        {
           closable.Close += this.Close();
        }
    }
}

在关闭窗口之前也解开委托。 现在在 viewmodel 中调用 Close Action 将关闭窗口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-20
    • 2015-02-04
    • 2017-07-10
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多