用户控件作为组件.无法访问父窗口
本文关键字:访问 窗口 组件 控件 用户 | 更新日期: 2023-09-27 18:07:03
我正在学习WPF和MVVM模式,我可能实现的东西不正确。
我想构建组件为我的应用程序的窗口使用用户控制对象,其中组件可以跨windows使用。例如,我有一个NewUnitUserControl,我打算将其用作对话框窗口的唯一组件,同时也用作主窗口的组件。
NewUnitUserControl.xaml:
<UserControl x:Class="Sample.Views.UserControls.NewUnitUserControl"
...
xmlns:local="clr-namespace:Sample.Views.UserControls">
<Grid>
<StackPanel Orientation="Vertical">
<Border>
<StackPanel Orientation="Horizontal">
<Label>Name:</Label>
<TextBox Text="{Binding Unit.Name}" Width="136"/>
</StackPanel>
</Border>
<Border HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<Border>
<Button Command="{Binding CreateUnitCommand}">Create</Button>
</Border>
<Border>
<Button Command="{Binding CancelCommand}">Cancel</Button>
</Border>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</UserControl>
NewUnitUserControl.xaml.cs:
namespace Sample.Views.UserControls
{
public partial class NewUnitUserControl : UserControl
{
public NewUnitUserControl()
{
InitializeComponent();
NewUnitViewModel nuvm = new NewUnitViewModel();
DataContext = nuvm;
if (nuvm.CloseAction == null)
{
var window = Window.GetWindow(this); // window evaluates to null
// after this line.
nuvm.CloseAction = new Action(window.Close);
}
}
}
}
NewUnitViewModel.cs
namespace Sample.ViewModels
{
internal class NewUnitViewModel : INotifyPropertyChanged
{
//Properties
private Unit _unit;
public Unit Unit
{
get { return _unit; }
set { _unit = value; OnPropertyChanged("Unit"); }
}
public Action CloseAction { get; set; }
private ICommand _createUnitCommand;
public ICommand CreateUnitCommand
{
get
{
if (_unitUpdateCommand == null)
_unitUpdateCommand = new RelayCommand(param => CreateUnit(), param => true);
return _unitUpdateCommand;
}
}
private ICommand _cancelCommand;
public ICommand CancelCommand
{
get
{
if(_cancelCommand == null)
_cancelCommand = new RelayCommand(param => Cancel(), param => true);
return _cancelCommand;
}
}
//Constructor
public CreateUnitViewModel()
{
_unit = new Models.Unit();
}
//Methods
public void CreateUnit()
{
Debug.Assert(false, String.Format("{0} was created.", Unit.Name));
}
public void Cancel()
{
this.CloseAction();
}
#region INotifyProperty Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
NewUnitDialogWindow.xaml:
<Window x:Class="Sample.Views.NewUnitWindow"
...
xmlns:local="clr-namespace:Sample.Views"
xmlns:controls="clr-namespace:Sample.Views.UserControls"
>
<controls:NewUnitUserControl />
</Window>
NewUnitDialogWindow.xaml.cs
namespace Sample.Views
{
public partial class NewUnitWindow : Window
{
public NewUnitWindow()
{
InitializeComponent();
}
}
}
完整源代码:GitHub
我立即面临的问题是,在我的实现中,我无法使用这里的解决方案访问用户控件的父窗口(参见NewUnitUserControl.xaml.cs中的评论)。我希望我的问题的根源是我没有正确理解MVVM模式。
我认为问题是用户控件还不知道父窗口是谁。尝试移动到Loaded事件:
private Window _parentWindow = null;
public NewUnitUserControl()
{
InitializeComponent();
Loaded += (s, e) =>
{
_parentWindow = Window.GetWindow(this);
/// whatever you are going to do with parent window
}
}
您还可以使用Prism工具包中的IEventAggregator或MvvmToolkit中的IMessenger(我认为这就是它的名称)从按钮的命令动作发送消息。
你试图访问父窗口的方式对我来说似乎不熟悉。
var window = window . getwindow (this);
请尝试以下代码。我编辑了你的,所以替换它:)
public NewUnitUserControl()
{
InitializeComponent();
CreateUnitViewModel cuvm = new CreateUnitViewModel();
DataContext = nuvm;
if (nuvm.CloseAction == null)
{
//var window = this.ParentForm; // window evaluates to null
// // after this line.
if(this.ParentForm != null)
cuvm.CloseAction = new Action(this.ParentForm.Close);
}
}