class 库的 2 个视图(同一实例)的 1 个 ViewModel 和 wpf 视图
1 ViewModel for 2 Views (same instance) for class library with wpf views
请多多包涵,因为我对这一切还很陌生。我目前正在尝试将我的两个视图绑定到我的 ViewModel 的同一个实例(在 xaml 中而不是代码隐藏)。 我的代码用于软件中的插件(输出是 class 库 .dll 文件),因此它没有设置为 C# WPF 应用程序(我没有 App.xaml)。我已经研究过使用 MVVM light、viewmodellocator 和所有其他在线找到的解决方案,但它们都依赖于 App.xaml,我不确定如何在我的案例中实施。
根据我正在为其开发插件的软件的文档;入口点是一个特定的 class(现在称之为 EntryPoint.cs)。 Main方法用于入口。在我的 Main 方法中,我创建了我的 MainView。
EntryPoint.cs:
public class EntryPoint
{
private MainView _MyForm;
public void Main(...)
{
....
_MyForm = new MainView();
_MyForm.ShowDialog();
}
}
在我的主视图构造函数中,我启动了我的 MainWindowViewModel。
Mainview.cs:
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
SecondView 是通过我的 MainView 上的按钮打开的,如下所示;这是我的 MainWindowViewModel 中的代码片段,其中包含用于打开我的 SecondView 的命令:
public void OpenSecondView()
{
....
SecondView newView = new SecondView (this);
SecondView.Show();
}
我之前通过在我的 SecondView 的构造函数中将视图模型作为参数传递来在我的代码隐藏中设置数据上下文:
public partial class SecondView: Window
{
public SecondView(MainViewModel viewModel)
{
InitializeComponent();
this.DataContext = viewModel;
}
}
如何在我的 xaml 中实现这一点?我想绑定到与我的 viewModel 相同的实例。有什么指导吗?
试试这个:
MainView.cs
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
var vm = new MainWindowViewModel();
vm.PropertyChanged += OnViewModelPropertyChanged;
this.DataContext = vm;
}
public void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof("OpenSecondViewCommand")
{
SecondView newView = new SecondView() { DataContext = this.DataContext };
SecondView.Show();
}
}
MainWindowViewModel.cs
// Get rid of your OpenSecondView() method that is tied to your Command. It is too tightly-
// coupled with the View. Instead, just use your Command public property and trigger the
// PropertyChanged event, then let the View layer deal with what happens when you trigger
// this Command. I don't know the name of your Command public property so I'm just going
// to assume it's called OpenSecondViewCommand. Something like this would suffice:
private RelayCommand openSecondViewCommand;
public RelayCommand OpenSecondViewCommand
{
get
{
if (this.openSecondViewCommand == null)
this.openSecondViewCommand = new RelayCommand(() => PropertyChanged?.Invoke(this, new PropertyEventArgs(nameof(OpenSecondViewCommand)));
return this.openSecondViewCommand;
}
}
SecondView.cs
// Remove the MainWindowViewModel parameter from your c'tor.
// Change it back to the way it was originally.
public partial class SecondView: Window
{
public SecondView()
{
InitializeComponent();
}
}
详细说明
MVVM 设计模式的一个主要方面是您通过将模型与 ViewModel 以及 ViewModel 与 View 分离和解耦来定义“关注点分离”。此设计模式以这种方式定义它,以便您可以用一个新的 UI 替换整个 UI,而无需触及您的 ViewModel 代码。在您的情况下,您已将 SecondView
嵌入到 MainWindowViewModel
中。这违反了 MVVM 设计模式。
将两个视图绑定到同一个 ViewModel 就像确保两个视图具有相同的 DataContext
一样简单。你可以看到我已经在 MainView.cs
中处理了这个问题,方法是将 SecondView
DataContext
属性 设置为 MainView
DataContext
。
SecondView newView = new SecondView() { DataContext = this.DataContext };
请多多包涵,因为我对这一切还很陌生。我目前正在尝试将我的两个视图绑定到我的 ViewModel 的同一个实例(在 xaml 中而不是代码隐藏)。 我的代码用于软件中的插件(输出是 class 库 .dll 文件),因此它没有设置为 C# WPF 应用程序(我没有 App.xaml)。我已经研究过使用 MVVM light、viewmodellocator 和所有其他在线找到的解决方案,但它们都依赖于 App.xaml,我不确定如何在我的案例中实施。
根据我正在为其开发插件的软件的文档;入口点是一个特定的 class(现在称之为 EntryPoint.cs)。 Main方法用于入口。在我的 Main 方法中,我创建了我的 MainView。
EntryPoint.cs:
public class EntryPoint
{
private MainView _MyForm;
public void Main(...)
{
....
_MyForm = new MainView();
_MyForm.ShowDialog();
}
}
在我的主视图构造函数中,我启动了我的 MainWindowViewModel。
Mainview.cs:
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
SecondView 是通过我的 MainView 上的按钮打开的,如下所示;这是我的 MainWindowViewModel 中的代码片段,其中包含用于打开我的 SecondView 的命令:
public void OpenSecondView()
{
....
SecondView newView = new SecondView (this);
SecondView.Show();
}
我之前通过在我的 SecondView 的构造函数中将视图模型作为参数传递来在我的代码隐藏中设置数据上下文:
public partial class SecondView: Window
{
public SecondView(MainViewModel viewModel)
{
InitializeComponent();
this.DataContext = viewModel;
}
}
如何在我的 xaml 中实现这一点?我想绑定到与我的 viewModel 相同的实例。有什么指导吗?
试试这个:
MainView.cs
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
var vm = new MainWindowViewModel();
vm.PropertyChanged += OnViewModelPropertyChanged;
this.DataContext = vm;
}
public void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof("OpenSecondViewCommand")
{
SecondView newView = new SecondView() { DataContext = this.DataContext };
SecondView.Show();
}
}
MainWindowViewModel.cs
// Get rid of your OpenSecondView() method that is tied to your Command. It is too tightly-
// coupled with the View. Instead, just use your Command public property and trigger the
// PropertyChanged event, then let the View layer deal with what happens when you trigger
// this Command. I don't know the name of your Command public property so I'm just going
// to assume it's called OpenSecondViewCommand. Something like this would suffice:
private RelayCommand openSecondViewCommand;
public RelayCommand OpenSecondViewCommand
{
get
{
if (this.openSecondViewCommand == null)
this.openSecondViewCommand = new RelayCommand(() => PropertyChanged?.Invoke(this, new PropertyEventArgs(nameof(OpenSecondViewCommand)));
return this.openSecondViewCommand;
}
}
SecondView.cs
// Remove the MainWindowViewModel parameter from your c'tor.
// Change it back to the way it was originally.
public partial class SecondView: Window
{
public SecondView()
{
InitializeComponent();
}
}
详细说明
MVVM 设计模式的一个主要方面是您通过将模型与 ViewModel 以及 ViewModel 与 View 分离和解耦来定义“关注点分离”。此设计模式以这种方式定义它,以便您可以用一个新的 UI 替换整个 UI,而无需触及您的 ViewModel 代码。在您的情况下,您已将 SecondView
嵌入到 MainWindowViewModel
中。这违反了 MVVM 设计模式。
将两个视图绑定到同一个 ViewModel 就像确保两个视图具有相同的 DataContext
一样简单。你可以看到我已经在 MainView.cs
中处理了这个问题,方法是将 SecondView
DataContext
属性 设置为 MainView
DataContext
。
SecondView newView = new SecondView() { DataContext = this.DataContext };