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