Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在WPF中引用从主窗口获取参数但尊重MVVM的子窗口_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 如何在WPF中引用从主窗口获取参数但尊重MVVM的子窗口

C# 如何在WPF中引用从主窗口获取参数但尊重MVVM的子窗口,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我实现了一些违反MVVM模式的东西,我想知道是否有一种MVVM方法可以做到这一点 我有一个窗口main窗口,它的DataContext绑定到一个名为ViewModel的类,该类实现了INotifyPropertyChanged 我还实现了一个窗口ChildWindow,当点击按钮时,它会以“对话框”的形式出现,使用RelayCommand。ChildWindow的数据上下文也绑定到ViewModel。此窗口用于填写新列表项的详细信息。我将视图作为CommandParameter传递给ViewMo

我实现了一些违反MVVM模式的东西,我想知道是否有一种MVVM方法可以做到这一点

我有一个窗口
main窗口
,它的DataContext绑定到一个名为
ViewModel
的类,该类实现了
INotifyPropertyChanged

我还实现了一个窗口
ChildWindow
,当点击按钮时,它会以“对话框”的形式出现,使用
RelayCommand
ChildWindow
的数据上下文也绑定到
ViewModel
。此窗口用于填写新列表项的详细信息。我将视图作为
CommandParameter
传递给
ViewModel
,以便
ChildWindow
可以与
main window
相比居中。这不是MVVM,我想更改它

首先,我以非MVVM的方式实现了这一点: 这是我在
main窗口中打开
ChildWindow
的按钮的XAML:

 <Button Name="BtnInsert" Width="50" Margin="10" Command="{Binding OpenChildWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">Add</Button>
行为准则:

class BehButtonNewWindow : Behavior<Button>
{
    private StListItemWindow _ListItemWindow;
    protected override void OnAttached()
    {
        AssociatedObject.Click += OnClickHandler;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Click -= OnClickHandler;
    }
    private void OnClickHandler(object sender, RoutedEventArgs routedEventArgs)
    {
        if (sender is Button button)
        {
            var win = Window.GetWindow(button);

            if (win != null)
            {
                _ListItemWindow = new ListItemWindow
                {
                    DataContext = win.DataContext,
                    Owner = win,
                    WindowStartupLocation = WindowStartupLocation.CenterOwner
                };

                _ListItemWindow.Show();
            }

        }
    }
}

我做错了什么?

这个答案要归功于威尔(见评论)

在处理车窗打开时:


打开窗口是一个UI问题。只需在codebehind中单击按钮,构建一个新窗口并将当前VM粘贴在其中。MVVM!=没有代码隐藏

在处理vm代码时:

[…]如果您的意思是底部的最后一点代码,请将其公开,并在打开新窗口之前让窗口调用它。用户界面非常了解视图模型。它们被设计为显示其状态并绑定到其属性


谢谢你的帮助

有关mvvm违规的可能重复-您可以查看@Sinatr,它不是重复的。链接到的问题涉及为新ViewModel实例创建新窗口。我的问题是创建一个绑定到同一个ViewModel实例的新窗口。但它仍然在创建一个新窗口,并将某种ViewModel附加到该窗口。打开窗口是一个UI问题。只需在codebehind中单击按钮,构建一个新窗口并将当前VM粘贴在其中。MVVM!=没有代码隐藏。
public class ViewModel : INotifyPropertyChanged
{
    private DataContext _ctx;
    private ListItem _currentListItem;
    private ObservableCollection<listItem> _listItems;

    private ListItemWindow _listItemWindow;
    private ICommand _openListItemWindowCommand;

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<ListItem> ListItems
    {
        get { return _listItems; }
        set
        {
            _listItems = value;
            OnPropertyChanged();
        }
    }

    public ListItem CurrentListItem
    {
        get { return _currentListItem; }
        set
        {
            _currentListItem = value;
            OnPropertyChanged();
        }
    }

    public ICommand OpenListItemWindowCommand
    {
        get { return _openListItemWindowCommand; }
        set
        {
            _openListItemWindowCommand = value;
            OnPropertyChanged();
        }
    }

    public ViewModel()
    {
        OpenListItemWindowCommand = new RelayCommand(this.OpenNewListItemWindow, this.CanOpenListItemWindow);
    }

    private void OpenNewListItemWindow(object parameter) 
    {
        CurrentListItem = new listItem(){Id = "testId"};
        _listItemWindow = new StListItemWindow(){DataContext = this};     
        _listItemWindow.Owner = (MainWindow)parameter;                   
        _listItemWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
        _listItemWindow.Closing += OnStListItemWindowClosing;    
        _listItemWindow.Show();
    }

    private bool CanOpenListItemWindow(object parameter) 
    {
        return true;
    }


    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
    <Button Name="BtnInsert" Width="50" Margin="10" Command="{Binding OpenListItemWindowCommand}" Content="Add">
        <i:Interaction.Behaviors>
            <behaviors:BehButtonNewWindow></behaviors:BehButtonNewWindow>
        </i:Interaction.Behaviors>
    </Button>
class BehButtonNewWindow : Behavior<Button>
{
    private StListItemWindow _ListItemWindow;
    protected override void OnAttached()
    {
        AssociatedObject.Click += OnClickHandler;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Click -= OnClickHandler;
    }
    private void OnClickHandler(object sender, RoutedEventArgs routedEventArgs)
    {
        if (sender is Button button)
        {
            var win = Window.GetWindow(button);

            if (win != null)
            {
                _ListItemWindow = new ListItemWindow
                {
                    DataContext = win.DataContext,
                    Owner = win,
                    WindowStartupLocation = WindowStartupLocation.CenterOwner
                };

                _ListItemWindow.Show();
            }

        }
    }
}
    private void OpenNewStListItemWindow(object parameter) 
    {
        CurrentListItem = new ListItem(){Id = "testId"}; 
}