使用MVVM从ViewModel单击“确定”按钮后,以编程方式关闭窗口

时间:2011-06-23 19:36:10

标签: c# wpf window viewmodel

我正在显示一个窗口。该实例是在ViewModel中创建并显示的(我知道错误的做法......)

NewWindow form = new NewWindow();
form.ShowDialog(); 

在这个表单中,我有一个OK_button,它在按下时正在做东西。这个表单中存在一个ViewModel,它具有来自OK_Button的OK命令。 按下该按钮后,我想从视图模型中以编程方式关闭该表单。我怎么能这样做?

我使用 WPF

更新

现在让我们看看我做错了什么:虽然我的Window带有ViewModel,但是这里没有触发DataContext事件!?

显示的窗口必须从ViewModel中关闭:

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

        private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            NewSchoolYearViewModel vm = (NewSchoolYearViewModel)e.NewValue;
            vm.CloseNewSchoolYearDialog += () => this.Close();              
        }
    }

为什么DataContextChanged甚至没有被触发?

我在我的窗口中使用此XAML:

<Window x:Class="TBM.View.NewSchoolYearWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:TBM.ViewModel"
        Title="Start a new school year"
        Height="412" Width="505" 
        WindowStartupLocation="CenterScreen"        
        WindowStyle="ThreeDBorderWindow"
        ResizeMode="CanResize" DataContextChanged="Window_DataContextChanged">
    <Window.Resources>

        <ViewModel:NewSchoolYearViewModel x:Key="NewSchoolYearViewModelID" />

    </Window.Resources>

    <Grid DataContext="{Binding ., Source={StaticResource NewSchoolYearViewModelID}}" Name="MainGrid">
        <TextBlock Height="27" HorizontalAlignment="Left" Margin="68,46,0,0" Name="textBlock1" Text="School year start" VerticalAlignment="Top" Width="98" />
        <TextBlock Height="27" HorizontalAlignment="Left" Margin="68,93,0,0" Name="textBlock2" Text="School year end" VerticalAlignment="Top" Width="98" />
        <TextBlock Height="27" HorizontalAlignment="Left" Margin="68,169,0,0" Name="textBlock4" Text="Database name:" VerticalAlignment="Top" Width="150" TextAlignment="Left" TextTrimming="CharacterEllipsis" />
        <TextBlock Height="27" HorizontalAlignment="Left" Margin="68,215,0,0" Name="textBlock3" Text="Directory:" VerticalAlignment="Top" Width="63" TextAlignment="Left" TextTrimming="CharacterEllipsis" />
        <TextBox IsReadOnly="True" Text="{Binding CurrentSchoolYear.Directory}"  Height="23" HorizontalAlignment="Left" Margin="172,212,0,0" Name="textBox3" VerticalAlignment="Top" Width="224" />
        <Button Command="{Binding OpenNewSchoolYearDialogCommand}" Content="DIR" Height="23" HorizontalAlignment="Right" Margin="0,211,27,0" Name="button1" VerticalAlignment="Top" Width="54" />
        <Button Command="{Binding CreateNewSchoolYearCommand}" Content="OK" Height="23" HorizontalAlignment="Left" Margin="381,299,0,0" Name="button2" VerticalAlignment="Top" Width="75" />
        <Button Content="Cancel" Height="23" HorizontalAlignment="Left" Margin="300,299,0,0" Name="button3" VerticalAlignment="Top" Width="75" />
        <DatePicker Height="25" HorizontalAlignment="Left" Margin="172,42,0,0" SelectedDate="{Binding CurrentSchoolYear.Start}" SelectedDateFormat="Long" VerticalAlignment="Top" Width="175" />
        <DatePicker Height="25" HorizontalAlignment="Left" Margin="172,89,0,0" SelectedDate="{Binding CurrentSchoolYear.End}" SelectedDateFormat="Long" VerticalAlignment="Top" Width="175" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="172,166,0,0" Name="textBox1" Text="{Binding CurrentSchoolYear.Name}" VerticalAlignment="Top" Width="175" />
    </Grid>
</Window>

1 个答案:

答案 0 :(得分:1)

在ViewModel中声明一个事件:

public event EventHandler<CloseRequestedEventArgs> CloseRequested;

protected virtual void OnCloseRequested(bool? dialogResult)
{
    var handler = CloseRequested;
    if (handler != null)
        handler(this, new CloseRequestedEventArgs(dialogResult));
}

...

public class CloseRequestedEventargs : EventArgs
{
    private readonly bool? _dialogResult;

    public CloseRequestedEventargs(bool? dialogResult)
    {
        _dialogResult = dialogResult;
    }

    public bool DialogResult { get { return _dialogResult; } }
}

并在代码隐藏中处理它:

var vm = (MyViewModel)DataContext;
vm.CloseRequested += vm_CloseRequested;

...

private void vm_CloseRequested(object sender, CloseRequestedEventArgs e)
{
    if (e.DialogResult.HasValue)
        this.DialogResult = e.DialogResult; // sets the dialog result AND closes the window
    else
        this.Close();
}