用户控件作为组件.无法访问父窗口 [英] User Control as components. No access to Parent Window

查看:32
本文介绍了用户控件作为组件.无法访问父窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 WPF 和 MVVM 模式,但我可能会错误地实现.

I am learning WPF and the MVVM pattern, and I may be implementing things incorrectly.

我想使用用户控制对象为我的应用程序窗口构建组件,其中组件可以跨 Windows 使用.例如,我有一个 NewUnitUserControl,我打算将它用作对话框窗口的唯一组件,也用作 MainWindow 的组件.

I want to build out components for my app's windows using User Control objects, where components could be used across Windows. For an example I have a NewUnitUserControl that I intend to use as the only component for a dialog window, and also as a component for the MainWindow.

NewUnitUserControl.xaml:

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:

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

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:

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

NewUnitDialogWindow.xaml.cs

namespace Sample.Views
{
    public partial class NewUnitWindow : Window
    {
        public NewUnitWindow()
        {
            InitializeComponent();
        }    
    }
}

完整来源:GitHub

我立即面临的问题是,在我的实现中,我无法使用解决方案访问用户控件的父窗口 此处(请参阅 NewUnitUserControl.xaml.cs 中的注释).我希望我的问题的根源在于我没有正确理解 MVVM 模式.

The problem I'm immediately facing is that with my implementation, I'm unable to access the User Control's parent window using the solution here (see the comment in NewUnitUserControl.xaml.cs). I expect the root of my issues is that I'm not understanding the MVVM pattern correctly.

推荐答案

我认为问题是用户控件还不知道父窗口是谁.尝试转到 Loaded 事件:

I think the problem is that the user control doesn't know who the parent window is yet. Try moving to the Loaded event:

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(我认为这就是它的名字)之类的东西从按钮的命令操作发送消息.

You could also send a message from the button's command action using something like IEventAggregator from the Prism toolkit or IMessenger (I think that is what it is called) from MvvmToolkit.

这篇关于用户控件作为组件.无法访问父窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆