c# - 如何从另一个窗口访问 DataContext?
问题描述
问题
当我打开
SecondView
并在其中键入内容TextBox
然后关闭Window
并重新打开它时,那里没有文本,好像它没有被绑定一样。我相信这是因为View
每次单击显示SecondView
我不知道如何在 不创建新实例的情况下访问
SecondViewModel
from my中的属性。MainViewModel
我希望能够从内部获得Name
财产SecondViewModel
GrabDataFromSecondViewModelCommand
从 开始MainView
,这就是它的样子。
...
xmlns:local="clr-namespace:Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<StackPanel>
<Button Command="{Binding ShowSecondViewCommand}"
Height="25" Width="100"/>
<Button Command="{Binding GrabDataFromSecondViewDataContext}"
Height="25" Width="100"/>
</StackPanel>
它是DataContext looks like this.
class MainViewModel
{
public RelayCommand ShowSecondViewCommand { get; set; }
public RelayCommand GrabDataFromSecondViewModelCommand { get; set; }
public MainViewModel()
{
ShowSecondViewCommand = new RelayCommand(o =>
{
var SecondView = new SecondView();
SecondView.ShowDialog();
}, o => true);
GrabDataFromSecondViewModelCommand = new RelayCommand(o =>
{
/*Not sure how to grab the data from SecondViewModel
without having to initialize a new instance of it.
*/
}, o => true);
}
}
SecondView
看起来像这样。
...
xmlns:local="clr-namespace:Views"
mc:Ignorable="d"
Title="SecondView" Height="450" Width="800">
<Window.DataContext>
<local:SecondViewModel/>
</Window.DataContext>
<Grid>
<TextBox Text="{Binding Name}"
Height="25" Width="100"/>
</Grid>
就像DataContext
这样。
class SecondViewModel : ObservableObject
{
public SecondViewModel()
{
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
}
我不妨把RelayCommand
&扔ObservableObject
在这里
可观察对象
类 ObservableObject : INotifyPropertyChanged { 公共事件 PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
中继命令
public class RelayCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> execute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
}
更新 所以我改变了 SHowCommand 来做到这一点
ShowSecondViewCommand = new RelayCommand(o =>
{
SecondViewModel = new SecondViewModel();
var SecondView = new SecondView(SecondViewModel);
SecondView.ShowDialog();
}, o => true);
然后在SecondView
windows初始化列表中我像这样设置DataContext
public SecondView(SecondViewModel svm)
{
DataContext = svm;
InitializeComponent();
}
每次命令打开窗口时,它都会使用一个新实例。
新的更新
现在我就这样了
public SecondViewModel SecondViewModel { get; } = new SecondViewModel();
public MainViewModel()
{
ShowSecondViewCommand = new RelayCommand(o =>
{
var SecondView = new SecondView(SecondViewModel);
SecondView.ShowDialog();
}, o => true);
它仍然可以编译,但它仍然会创建一个新实例。
解决方案
使用组合并让您MainViewModel
对SecondViewModel
. 这样你就可以直接从MainViewModel
. 当创建一个新实例SecondView
(不应该是视图模型的责任)时,只需将 的引用分配给SecondViewModel
视图DataContext
并从SecondView
.
class MainViewModel
{
public SecondViewModel SecondViewModel { get; }
public RelayCommand ShowSecondViewCommand { get; set; }
public RelayCommand GrabDataFromSecondViewModelCommand { get; set; }
public MainViewModel()
{
this.SecondViewModel = new SecondViewModel();
ShowSecondViewCommand = new RelayCommand(o =>
{
var SecondView = new SecondView() { DataContext = this.SecondViewModel };
SecondView.ShowDialog();
}, o => true);
GrabDataFromSecondViewModelCommand = new RelayCommand(o =>
{
// Directly access the view model
string valueFromAssociatedViewModel = this.SecondViewModel.Name;
}, o => true);
}
}
我认为您的最后一次更新应该有效。
推荐阅读
- mapbox - 在地图上为 Mapbox 上的地址创建自定义区域的文档
- java - Spring Boot - 创建名称为“”的bean时出错
- apache-spark - Spark Stateful Structured Streaming:状态在 mapGroupsWithState 中变得太大
- php - Codeigniter- call_user_func_array() 期望参数 1 是一个有效的回调,类 'Error' 没有方法 'index'
- javascript - 通过 WebPack 将 Bootstrap 加载到 Wordpress 时,ReactJS 代码拆分导致错误
- google-apps-script - 获取值跳过错误
- swiftui - SwiftUI:API 调用后如何移动 MapPin?
- javascript - 跳过字符串的一部分并用正则表达式替换匹配
- android-studio - Android Studio 4.0.1 丢弃连接的设备
- c++ - 根据模板类型使类成员变量可选的非详细解决方案?