我有一个Button
关闭我的窗口时点击它:
<Button x:Name="buttonOk" IsCancel="True">Ok</Button>
在我向Command
添加Button
之前,这很好。
<Button x:Name="buttonOk"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
现在它不会因为我正在处理Command
而关闭。我可以通过EventHandler
加入并调用this.Close()
即
<Button x:Name="buttonOk"
Click="closeWindow"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
但现在我的代码中有代码,即方法SaveCommand
。我正在使用MVVM模式,SaveCommand
是我代码中唯一的代码。
如何以不同方式执行此操作以避免使用代码?
答案 0 :(得分:52)
我刚刚就这个主题完成了blog post。简而言之,使用Action
和get
访问者向ViewModel添加set
属性。然后从Action
构造函数中定义View
。最后,在应关闭窗口的bound命令中调用您的操作。
在ViewModel中:
public Action CloseAction { get; set;}
并在View
构造函数中:
private View()
{
InitializeComponent();
ViewModel vm = new ViewModel();
this.DataContext = vm;
if ( vm.CloseAction == null )
vm.CloseAction = new Action(this.Close);
}
最后,在任何应该关闭窗口的绑定命令中,我们可以简单地调用
CloseAction(); // Calls Close() method of the View
这对我有用,看起来像是一个相当优雅的解决方案,并为我节省了大量编码。
答案 1 :(得分:22)
不幸的是,在MVVM中显示窗口是一个真正的痛苦,所以你需要做很多基础设施工作或使用像Cinch这样的MVVM框架。如果你想花时间自己做here's Cinch如何做到的链接。
很好,你试图将任何逻辑排除在View之外,但如果你这样做,它真的不是世界末日。在这种情况下,它听起来不会导致太多问题。
答案 2 :(得分:15)
有人评论说,我发布的代码不是MVVM友好的,第二种解决方案怎么样?
第1,不是MVVM解决方案(我不会删除它作为参考)
XAML:
<Button Name="okButton" Command="{Binding OkCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">OK</Button>
视图模型:
public ICommand OkCommand
{
get
{
if (_okCommand == null)
{
_okCommand = new ActionCommand<Window>(DoOk, CanDoOk);
}
return _okCommand ;
}
}
void DoOk(Window win)
{
// Your Code
win.DialogResult = true;
win.Close();
}
bool CanDoOk(Window win) { return true; }
第二,可能是更好的解决方案: 使用附加行为
XAML
<Button Content="Ok and Close" Command="{Binding OkCommand}" b:CloseOnClickBehaviour.IsEnabled="True" />
查看模型
public ICommand OkCommand
{
get { return _okCommand; }
}
行为类 类似的东西:
public static class CloseOnClickBehaviour
{
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached(
"IsEnabled",
typeof(bool),
typeof(CloseOnClickBehaviour),
new PropertyMetadata(false, OnIsEnabledPropertyChanged)
);
public static bool GetIsEnabled(DependencyObject obj)
{
var val = obj.GetValue(IsEnabledProperty);
return (bool)val;
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
static void OnIsEnabledPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
{
var button = dpo as Button;
if (button == null)
return;
var oldValue = (bool)args.OldValue;
var newValue = (bool)args.NewValue;
if (!oldValue && newValue)
{
button.Click += OnClick;
}
else if (oldValue && !newValue)
{
button.PreviewMouseLeftButtonDown -= OnClick;
}
}
static void OnClick(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button == null)
return;
var win = Window.GetWindow(button);
if (win == null)
return;
win.Close();
}
}
答案 3 :(得分:12)
我个人会用一种行为来做这件事:
public class WindowCloseBehaviour : Behavior<Window>
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Command",
typeof(ICommand),
typeof(WindowCloseBehaviour));
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register(
"CommandParameter",
typeof(object),
typeof(WindowCloseBehaviour));
public static readonly DependencyProperty CloseButtonProperty =
DependencyProperty.Register(
"CloseButton",
typeof(Button),
typeof(WindowCloseBehaviour),
new FrameworkPropertyMetadata(null, OnButtonChanged));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public Button CloseButton
{
get { return (Button)GetValue(CloseButtonProperty); }
set { SetValue(CloseButtonProperty, value); }
}
private static void OnButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var window = (Window)((WindowCloseBehaviour)d).AssociatedObject;
((Button) e.NewValue).Click +=
(s, e1) =>
{
var command = ((WindowCloseBehaviour)d).Command;
var commandParameter = ((WindowCloseBehaviour)d).CommandParameter;
if (command != null)
{
command.Execute(commandParameter);
}
window.Close();
};
}
}
然后,您可以将此附加到Window
和Button
进行处理:
<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:WpfApplication6"
Title="Window1" Height="300" Width="300">
<i:Interaction.Behaviors>
<local:WindowCloseBehaviour CloseButton="{Binding ElementName=closeButton}"/>
</i:Interaction.Behaviors>
<Grid>
<Button Name="closeButton">Close</Button>
</Grid>
</Window>
我在这里添加了Command
和CommandParameter
,因此您可以在Window
关闭之前运行命令。
答案 4 :(得分:8)
非常干净,MVVM方式是使用InteractionTrigger
中定义的CallMethodAction
和Microsoft.Interactivity.Core
您需要添加两个名称空间,如下所示
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
和程序集 System.Windows.Interactivity 和 Microsoft.Expression.Interactions ,然后在xaml代码下面。
<Button Content="Save" Command="{Binding SaveCommand}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction MethodName="Close"
TargetObject="{Binding RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType=Window}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
您不需要任何代码或其他任何代码,也可以调用Window
的任何其他方法。
答案 5 :(得分:7)
对于小型应用程序,我使用自己的Application Controller来显示,关闭和处理Windows和DataContexts。它是应用程序UI的中心点。
这是这样的:
//It is singleton, I will just post 2 methods and their invocations
public void ShowNewWindow(Window window, object dataContext = null, bool dialog = true)
{
window.DataContext = dataContext;
addToWindowRegistry(dataContext, window);
if (dialog)
window.ShowDialog();
else
window.Show();
}
public void CloseWindow(object dataContextSender)
{
var correspondingWindows = windowRegistry.Where(c => c.DataContext.Equals(dataContextSender)).ToList();
foreach (var pair in correspondingWindows)
{
pair.Window.Close();
}
}
以及来自 ViewModels 的调用:
// Show new Window with DataContext
ApplicationController.Instance.ShowNewWindow(
new ClientCardsWindow(),
new ClientCardsVM(),
false);
// Close Current Window from viewModel
ApplicationController.Instance.CloseWindow(this);
当然,您可以在我的解决方案中找到一些限制。再说一次:我将它用于小型项目,这就足够了。如果您有兴趣,我可以在这里或其他地方发布完整的代码/
答案 6 :(得分:5)
我使用 发布订阅模式 来处理复杂的类依赖项:
<强>视图模型:强>
public class ViewModel : ViewModelBase
{
public ViewModel()
{
CloseComand = new DelegateCommand((obj) =>
{
MessageBus.Instance.Publish(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, null);
});
}
}
<强>窗口:强>
public partial class SomeWindow : Window
{
Subscription _subscription = new Subscription();
public SomeWindow()
{
InitializeComponent();
_subscription.Subscribe(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, obj =>
{
this.Close();
});
}
}
您可以利用Bizmonger.Patterns获取MessageBus。
<强> MessageBus 强>
public class MessageBus
{
#region Singleton
static MessageBus _messageBus = null;
private MessageBus() { }
public static MessageBus Instance
{
get
{
if (_messageBus == null)
{
_messageBus = new MessageBus();
}
return _messageBus;
}
}
#endregion
#region Members
List<Observer> _observers = new List<Observer>();
List<Observer> _oneTimeObservers = new List<Observer>();
List<Observer> _waitingSubscribers = new List<Observer>();
List<Observer> _waitingUnsubscribers = new List<Observer>();
int _publishingCount = 0;
#endregion
public void Subscribe(string message, Action<object> response)
{
Subscribe(message, response, _observers);
}
public void SubscribeFirstPublication(string message, Action<object> response)
{
Subscribe(message, response, _oneTimeObservers);
}
public int Unsubscribe(string message, Action<object> response)
{
var observers = new List<Observer>(_observers.Where(o => o.Respond == response).ToList());
observers.AddRange(_waitingSubscribers.Where(o => o.Respond == response));
observers.AddRange(_oneTimeObservers.Where(o => o.Respond == response));
if (_publishingCount == 0)
{
observers.ForEach(o => _observers.Remove(o));
}
else
{
_waitingUnsubscribers.AddRange(observers);
}
return observers.Count;
}
public int Unsubscribe(string subscription)
{
var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription).ToList());
observers.AddRange(_waitingSubscribers.Where(o => o.Subscription == subscription));
observers.AddRange(_oneTimeObservers.Where(o => o.Subscription == subscription));
if (_publishingCount == 0)
{
observers.ForEach(o => _observers.Remove(o));
}
else
{
_waitingUnsubscribers.AddRange(observers);
}
return observers.Count;
}
public void Publish(string message, object payload)
{
_publishingCount++;
Publish(_observers, message, payload);
Publish(_oneTimeObservers, message, payload);
Publish(_waitingSubscribers, message, payload);
_oneTimeObservers.RemoveAll(o => o.Subscription == message);
_waitingUnsubscribers.Clear();
_publishingCount--;
}
private void Publish(List<Observer> observers, string message, object payload)
{
Debug.Assert(_publishingCount >= 0);
var subscribers = observers.Where(o => o.Subscription.ToLower() == message.ToLower());
foreach (var subscriber in subscribers)
{
subscriber.Respond(payload);
}
}
public IEnumerable<Observer> GetObservers(string subscription)
{
var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription));
return observers;
}
public void Clear()
{
_observers.Clear();
_oneTimeObservers.Clear();
}
#region Helpers
private void Subscribe(string message, Action<object> response, List<Observer> observers)
{
Debug.Assert(_publishingCount >= 0);
var observer = new Observer() { Subscription = message, Respond = response };
if (_publishingCount == 0)
{
observers.Add(observer);
}
else
{
_waitingSubscribers.Add(observer);
}
}
#endregion
}
}
<强>订阅强>
public class Subscription
{
#region Members
List<Observer> _observerList = new List<Observer>();
#endregion
public void Unsubscribe(string subscription)
{
var observers = _observerList.Where(o => o.Subscription == subscription);
foreach (var observer in observers)
{
MessageBus.Instance.Unsubscribe(observer.Subscription, observer.Respond);
}
_observerList.Where(o => o.Subscription == subscription).ToList().ForEach(o => _observerList.Remove(o));
}
public void Subscribe(string subscription, Action<object> response)
{
MessageBus.Instance.Subscribe(subscription, response);
_observerList.Add(new Observer() { Subscription = subscription, Respond = response });
}
public void SubscribeFirstPublication(string subscription, Action<object> response)
{
MessageBus.Instance.SubscribeFirstPublication(subscription, response);
}
}
答案 7 :(得分:5)
我试图以一些通用的MVVM方式解决这个问题,但我总是发现我最终得到了不必要的复杂逻辑。为了实现密切的行为,我已经从没有代码的规则中做出了例外,并且仅仅使用代码中的良好ol'事件:
XAML:
<Button Content="Close" Click="OnCloseClicked" />
代码背后:
private void OnCloseClicked(object sender, EventArgs e)
{
Visibility = Visibility.Collapsed;
}
虽然我希望使用命令/ MVVM可以更好地支持这一点,但我认为没有比使用事件更简单,更清晰的解决方案。
答案 8 :(得分:3)
此任务有一个有用的行为,它不会破坏MVVM,一种与Expression Blend 3一起引入的行为,允许View挂钩到ViewModel中完全定义的命令。
此行为演示了一种允许使用的简单技术 ViewModel用于管理View中的结束事件 Model-View-ViewModel应用程序。
这允许您在View(UserControl)中连接一个行为 将提供对控件窗口的控制,允许ViewModel 控制是否可以通过标准ICommands关闭窗口。
Using Behaviors to Allow the ViewModel to Manage View Lifetime in M-V-VM
http://gallery.expression.microsoft.com/WindowCloseBehavior/
以上链接已归档为http://code.msdn.microsoft.com/Window-Close-Attached-fef26a66#content
答案 9 :(得分:2)
在您当前的窗口xaml.cs
文件中,调用以下代码:
var curWnd = Window.GetWindow(this); // passing current window context
curWnd?.Close();
这应该做的事。
它对我有用,希望对您也一样)
答案 10 :(得分:1)
我在这个主题上挣扎了一段时间,最终采用了与MVVM一致的最简单的方法:让按钮执行命令,完成所有繁重的操作并让按钮的Click处理程序关闭窗口。
<强> XAML 强>
<Button x:Name="buttonOk"
Click="closeWindow"
Command="{Binding SaveCommand}" />
<强> XAML.cs 强>
public void closeWindow()
{
this.DialogResult = true;
}
<强> SaveCommand.cs 强>
// I'm in my own file, not the code-behind!
是的,仍然存在代码隐藏,但没有任何内在的坏处。从OO的角度来看,它对我来说是最有意义的,只是告诉窗口关闭它。
答案 11 :(得分:1)
我们在.xaml定义中有name属性:
Open Folder in File explorer
然后我们有了按钮:
x:Name="WindowsForm"
然后在ViewModel中:
<Button Command="{Binding CloseCommand}"
CommandParameter="{Binding ElementName=WindowsForm}" />
最后,行动方法:
public DelegateCommand <Object> CloseCommand { get; private set; }
Constructor for that view model:
this.CloseCommand = new DelegateCommand<object>(this.CloseAction);
我使用此代码关闭应用程序的弹出窗口..
答案 12 :(得分:1)
我发现自己必须在基于.Net Core 3.0的WPF应用程序上执行此操作,不幸的是, Microsoft.Xaml.Behaviors.Wpf NuGet程序包中尚未正式提供行为支持。< / p>
相反,我选择了一种使用Façade设计模式的解决方案。
接口:
public interface IWindowFacade
{
void Close();
}
窗口:
public partial class MainWindow : Window, IWindowFacade
…
视图模型上的标准命令属性:
public ICommand ExitCommand
…
控件绑定:
<MenuItem Header="E_xit" Command="{Binding ExitCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
命令:
public class ExitCommand : ICommand
{
…
public void Execute(object parameter)
{
var windowFacade = parameter as IWindowFacade;
windowFacade?.Close();
}
…
}
由于Close()
类已经实现了Window
方法,因此将façade接口应用于窗口是UI层中唯一所需的代码(对于此简单示例)。表示层中的命令避免了对视图/ UI层的任何依赖,因为它不知道在调用立面上的Close
方法时在说什么。
答案 13 :(得分:0)
我一直在寻找解决同一问题的方法,并发现做以下工作正常。解决方案类似于OP在他的问题中提到的一些差异:
无需IsCancel
属性。
后面的代码不应该关闭窗口。只需设置DialogResult
在我的情况下,它首先执行代码,然后查看绑定到按钮的模型命令。
XAML
<Button x:Name="buttonOk" Click="Save_Click" Command="{Binding SaveCommand}">OK</Button>
背后的代码
private void Apply_OnClick(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
查看模型
private void Save()
{
// Save data.
}
希望这有帮助。
答案 14 :(得分:0)
你可以改写这个问题,并通过这样做 - 提出另一个解决方案。 如何在MVVM环境中启用视图,视图模型和诸如此类的东西之间的通信? 您可以使用Mediator模式。它基本上是一个通知系统。对于实际的Mediator实现,谷歌为它或问我,我可以发送电子邮件。
创建一个命令,其目的是关闭视图。
public void Execute( object parameter )
{
this.viewModel.DisposeMyStuff();
Mediator.NotifyColleagues(Mediator.Token.ConfigWindowShouldClose);
}
调解员将发出通知(令牌)
在View codebehind构造函数中监听此通知(令牌):
public ClientConfigView()
{
InitializeComponent();
Mediator.ListenOn(Mediator.Token.ConfigWindowShouldClose, callback => this.Close() );
}
答案 15 :(得分:0)
我在Silverlight中有以下解决方案。也将在WPF。
ChildWindowExt.cs:
namespace System.Windows.Controls
{
public class ChildWindowExt : ChildWindow
{
public static readonly DependencyProperty IsOpenedProperty =
DependencyProperty.Register(
"IsOpened",
typeof(bool),
typeof(ChildWindowExt),
new PropertyMetadata(false, IsOpenedChanged));
private static void IsOpenedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == false)
{
ChildWindowExt window = d as ChildWindowExt;
window.Close();
}
else if ((bool)e.NewValue == true)
{
ChildWindowExt window = d as ChildWindowExt;
window.Show();
}
}
public bool IsOpened
{
get { return (bool)GetValue(IsOpenedProperty); }
set { SetValue(IsOpenedProperty, value); }
}
protected override void OnClosing(ComponentModel.CancelEventArgs e)
{
this.IsOpened = false;
base.OnClosing(e);
}
protected override void OnOpened()
{
this.IsOpened = true;
base.OnOpened();
}
}
}
ItemWindow.xaml:
<extControls:ChildWindowExt
x:Class="MyProject.ItemWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:extControls="clr-namespace:System.Windows.Controls"
Title="{Binding Title}" IsOpened="{Binding IsOpened, Mode=TwoWay}" Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Button Command="{Binding UpdateCommand}" Content="OK" Width="70" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</extControls:ChildWindowExt>
ItemViewModel.cs:
private bool _IsOpened;
public bool IsOpened
{
get
{
return _IsOpened;
}
set
{
if (!Equals(_IsOpened, value))
{
_IsOpened = value;
RaisePropertyChanged("IsOpened");
}
}
}
private RelayCommand _UpdateCommand;
/// <summary>
/// Insert / Update data entity
/// </summary>
public RelayCommand UpdateCommand
{
get
{
if (_UpdateCommand == null)
{
_UpdateCommand = new RelayCommand(
() =>
{
// Insert / Update data entity
...
IsOpened = false;
},
() =>
{
return true;
});
}
return _UpdateCommand;
}
}
ItemsViewModel.cs:
private RelayCommand _InsertItemCommand;
/// <summary>
///
/// </summary>
public RelayCommand InsertItemCommand
{
get
{
if (_InsertItemCommand == null)
{
_InsertItemCommand = new RelayCommand(
() =>
{
ItemWindow itemWin = new ItemWindow();
itemWin.DataContext = new ItemViewModel();
itemWin.Show();
// OR
// ItemWindow itemWin = new ItemWindow();
// ItemViewModel newItem = new ItemViewModel();
// itemWin.DataContext = newItem;
// newItem.IsOpened = true;
},
() =>
{
return true;
});
}
return _InsertItemCommand;
}
}
MainPage.xaml中:
<Grid x:Name="LayoutRoot">
<Button Command="{Binding InsertItemCommand}" Content="Add New" Width="70" HorizontalAlignment="Left" VerticalAlignment="Center" />
</Grid>
祝大家好主意和项目; - )
答案 16 :(得分:0)
这可能对您有所帮助,使用mvvm以最少的代码关闭wpf窗口:http://jkshay.com/closing-a-wpf-window-using-mvvm-and-minimal-code-behind/
答案 17 :(得分:0)
我认为最简单的方法还没有被包括在内(差不多)。而不是使用添加新依赖项的行为,只需使用附加属性:
using System;
using System.Windows;
using System.Windows.Controls;
public class DialogButtonManager
{
public static readonly DependencyProperty IsAcceptButtonProperty = DependencyProperty.RegisterAttached("IsAcceptButton", typeof(bool), typeof(DialogButtonManager), new FrameworkPropertyMetadata(OnIsAcceptButtonPropertyChanged));
public static readonly DependencyProperty IsCancelButtonProperty = DependencyProperty.RegisterAttached("IsCancelButton", typeof(bool), typeof(DialogButtonManager), new FrameworkPropertyMetadata(OnIsCancelButtonPropertyChanged));
public static void SetIsAcceptButton(UIElement element, bool value)
{
element.SetValue(IsAcceptButtonProperty, value);
}
public static bool GetIsAcceptButton(UIElement element)
{
return (bool)element.GetValue(IsAcceptButtonProperty);
}
public static void SetIsCancelButton(UIElement element, bool value)
{
element.SetValue(IsCancelButtonProperty, value);
}
public static bool GetIsCancelButton(UIElement element)
{
return (bool)element.GetValue(IsCancelButtonProperty);
}
private static void OnIsAcceptButtonPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
if ((bool)e.NewValue)
{
SetAcceptButton(button);
}
else
{
ResetAcceptButton(button);
}
}
}
private static void OnIsCancelButtonPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
if ((bool)e.NewValue)
{
SetCancelButton(button);
}
else
{
ResetCancelButton(button);
}
}
}
private static void SetAcceptButton(Button button)
{
Window window = Window.GetWindow(button);
button.Command = new RelayCommand(new Action<object>(ExecuteAccept));
button.CommandParameter = window;
}
private static void ResetAcceptButton(Button button)
{
button.Command = null;
button.CommandParameter = null;
}
private static void ExecuteAccept(object buttonWindow)
{
Window window = (Window)buttonWindow;
window.DialogResult = true;
}
private static void SetCancelButton(Button button)
{
Window window = Window.GetWindow(button);
button.Command = new RelayCommand(new Action<object>(ExecuteCancel));
button.CommandParameter = window;
}
private static void ResetCancelButton(Button button)
{
button.Command = null;
button.CommandParameter = null;
}
private static void ExecuteCancel(object buttonWindow)
{
Window window = (Window)buttonWindow;
window.DialogResult = false;
}
}
然后将其设置在对话框按钮上:
<UniformGrid Grid.Row="2" Grid.Column="1" Rows="1" Columns="2" Margin="3" >
<Button Content="Accept" IsDefault="True" Padding="3" Margin="3,0,3,0" DialogButtonManager.IsAcceptButton="True" />
<Button Content="Cancel" IsCancel="True" Padding="3" Margin="3,0,3,0" DialogButtonManager.IsCancelButton="True" />
</UniformGrid>
答案 18 :(得分:0)
我也不得不处理这个问题,所以这里是我的解决方案。它对我很有用。
1。创建类DelegateCommand
public class DelegateCommand<T> : ICommand
{
private Predicate<T> _canExecuteMethod;
private readonly Action<T> _executeMethod;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<T> executeMethod) : this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Predicate<T> canExecuteMethod)
{
this._canExecuteMethod = canExecuteMethod;
this._executeMethod = executeMethod ?? throw new ArgumentNullException(nameof(executeMethod), "Command is not specified.");
}
public void RaiseCanExecuteChanged()
{
if (this.CanExecuteChanged != null)
CanExecuteChanged(this, null);
}
public bool CanExecute(object parameter)
{
return _canExecuteMethod == null || _canExecuteMethod((T)parameter) == true;
}
public void Execute(object parameter)
{
_executeMethod((T)parameter);
}
}
2。定义命令
public DelegateCommand<Window> CloseWindowCommand { get; private set; }
public MyViewModel()//ctor of your viewmodel
{
//do something
CloseWindowCommand = new DelegateCommand<Window>(CloseWindow);
}
public void CloseWindow(Window win) // this method is also in your viewmodel
{
//do something
win?.Close();
}
3。在视图中绑定您的命令
public MyView(Window win) //ctor of your view, window as parameter
{
InitializeComponent();
MyButton.CommandParameter = win;
MyButton.Command = ((MyViewModel)this.DataContext).CloseWindowCommand;
}
4。现在是窗口
Window win = new Window()
{
Title = "My Window",
Height = 800,
Width = 800,
WindowStartupLocation = WindowStartupLocation.CenterScreen,
};
win.Content = new MyView(win);
win.ShowDialog();
这样就可以了,你也可以在xaml文件中绑定命令,找到带有FindAncestor的窗口并将其绑定到命令参数。
答案 19 :(得分:0)
在wpf中关闭对我有用的窗口的解决方案在这里没有得到回答,所以我想我也将添加我的解决方案。
private static Window GetWindow(DependencyObject sender)
{
Window window = null;
if (sender is Window)
window = (Window)sender;
if (window == null)
window = Window.GetWindow(sender);
return window;
}
private void CloseWindow(object sender, RoutedEventArgs e)
{
var button = (Button)sender as DependencyObject;
Window window = GetWindow(button);
if (window != null)
window.Close();
// window.Visibility = Visibility.Hidden;
// choose between window.close or set window.visibility to close or hide the window.
// }
}
将CloseWindow事件添加到窗口中的按钮,如下所示。
<Button Content="Cancel" Click="CloseWindow" >
答案 20 :(得分:0)
简单的方法是在saveComand实现上关闭窗口。 使用下面的代码关闭窗口。
Application.Current.Windows[1].Close();
它将关闭子窗口。
答案 21 :(得分:0)
没有任何依赖。
<Window ...>
...
<Button Command="{x:Static SystemCommands.CloseWindowCommand}" />
</Window>
答案 22 :(得分:-1)
你可以在没有代码的情况下做到这一点。创建命令,在执行方法调用&#34;保存&#34; viewmodel上的方法以及在编辑窗口上调用close方法之后,可以通过参数传递给命令:
filesystem.root.createReader()
保存并关闭按钮XAML:
gotDir.createReader()