如何为多个 windows 创建一个 DataContext 实例?
How can I create only one instance of a DataContext for multiple windows?
所以我有一个 WPF 程序,其中有一个 ViewModel 和几个 windows。我通常像这样为我的 ViewModel 添加 DataContext:
<Window.DataContext>
<local:PrintView x:Name="printerView"/>
</Window.DataContext>
但是如果我那样做,我会遇到创建多个 ViewModel 实例的问题,每个实例一个 window。这意味着如果我在一个 window 中更改 属性,另一个 window 的相同 属性 不会更改。
现在我在 App.xaml 中这样定义它:
<Application.Resources>
<ResourceDictionary>
<local:PrintView x:Key="printView"/>
</ResourceDictionary>
</Application.Resources>
每个 window 中的地址如下:
DataContext="{StaticResource printView}"
但现在的问题是我想在没有 App.Xaml 的情况下创建整个内容。有谁知道我如何在没有 App.xaml 的情况下创建相同的结果?以及没有图书馆。
我正在使用 .NET Framework 4.8
编辑
我现在已经实现了来自@mm8 的解决方案。但是,它似乎仍然不起作用。 Xaml 部分一切正常,我可以访问这些属性。但是,后面的代码存在问题,即当我 select 一个 window 中的值并将其保存在 属性:
SecondWindow
因此将 selected 值保存在 属性:
SelectedItem="{Binding selected_printer, Mode=TwoWay}"
但是我想在另一个window中访问这个改变的值,是否像这样:
var vm = (ViewModel)this.DataContext;
vm.selected_printer
或者像这样:
ApplicationService.Instance.PrintView.selected_printer
无论我如何尝试在另一个 window 中访问之前更改的 属性,属性 都不会在另一个 window 中更新为新的 window值。
所以这个值:
SecondWindow
未转移到其他window且未更新
我选择的打印机定义:
private string _selected_printer;
public string selected_printer
{
get
{
return _selected_printer;
}
set
{
_selected_printer = value;
NotifyPropertyChanged(nameof(selected_printer));
}
}
我的 ViewModel 定义:
public class PrintView: INotifyPropertyChanged
我的 属性 更改的内容:
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
您无需使用 App.xaml
即可创建全局资源。您可以创建自己的 application-wide 服务 class 并在那里设置您的视图模型:
public sealed class ApplicationService
{
private ApplicationService() { }
public static ApplicationService Instance { get; } = new ApplicationService();
public PrintView PrintView { get; } = new PrintView();
}
用法:
DataContext="{Binding PrintView, Source={x:Static local:ApplicationService.Instance}}"
这基本上就是 view-model 定位器的工作原理(假设 PrintView
实际上是一个视图模型,尽管它的名字...)
所以我有一个 WPF 程序,其中有一个 ViewModel 和几个 windows。我通常像这样为我的 ViewModel 添加 DataContext:
<Window.DataContext>
<local:PrintView x:Name="printerView"/>
</Window.DataContext>
但是如果我那样做,我会遇到创建多个 ViewModel 实例的问题,每个实例一个 window。这意味着如果我在一个 window 中更改 属性,另一个 window 的相同 属性 不会更改。
现在我在 App.xaml 中这样定义它:
<Application.Resources>
<ResourceDictionary>
<local:PrintView x:Key="printView"/>
</ResourceDictionary>
</Application.Resources>
每个 window 中的地址如下:
DataContext="{StaticResource printView}"
但现在的问题是我想在没有 App.Xaml 的情况下创建整个内容。有谁知道我如何在没有 App.xaml 的情况下创建相同的结果?以及没有图书馆。
我正在使用 .NET Framework 4.8
编辑
我现在已经实现了来自@mm8 的解决方案。但是,它似乎仍然不起作用。 Xaml 部分一切正常,我可以访问这些属性。但是,后面的代码存在问题,即当我 select 一个 window 中的值并将其保存在 属性:
SecondWindow
因此将 selected 值保存在 属性:
SelectedItem="{Binding selected_printer, Mode=TwoWay}"
但是我想在另一个window中访问这个改变的值,是否像这样:
var vm = (ViewModel)this.DataContext;
vm.selected_printer
或者像这样:
ApplicationService.Instance.PrintView.selected_printer
无论我如何尝试在另一个 window 中访问之前更改的 属性,属性 都不会在另一个 window 中更新为新的 window值。
所以这个值: SecondWindow 未转移到其他window且未更新
我选择的打印机定义:
private string _selected_printer;
public string selected_printer
{
get
{
return _selected_printer;
}
set
{
_selected_printer = value;
NotifyPropertyChanged(nameof(selected_printer));
}
}
我的 ViewModel 定义:
public class PrintView: INotifyPropertyChanged
我的 属性 更改的内容:
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
您无需使用 App.xaml
即可创建全局资源。您可以创建自己的 application-wide 服务 class 并在那里设置您的视图模型:
public sealed class ApplicationService
{
private ApplicationService() { }
public static ApplicationService Instance { get; } = new ApplicationService();
public PrintView PrintView { get; } = new PrintView();
}
用法:
DataContext="{Binding PrintView, Source={x:Static local:ApplicationService.Instance}}"
这基本上就是 view-model 定位器的工作原理(假设 PrintView
实际上是一个视图模型,尽管它的名字...)