我正在尝试从父视图模型访问子窗口视图模型的属性值。我正在从父视图模型调用窗口。我想根据子视图模型中的操作在主窗口中进行更改。我无法在父视图模型中获取子视图模型的任何值。我正在 MVVM 模式中尝试这个。
对话框界面
public interface IWindowService
{
void OpenDialogWindow(DialogViewModel vm);
}
父视图模型
public class FunctionalViewModel : INotifyPropertyChanged
{
private readonly IWindowService _windowService;
private string connectionString;
public string ConnectionString
{
get { return connectionString; }
set
{
connectionString = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ConnectionString"));
}
}
public FunctionalViewModel(IWindowService windowService)
{
BuildConnectionCommand = new RelayCommand(new Action<object>(BuildConnectionString));
_windowService = windowService;
}
private void BuildConnectionString(object obj)
{
MessageBox.Show("will open a window");
_windowService.OpenDialogWindow(new DialogViewModel());
}
}
子视图模型
public class DialogViewModel : FunctionalViewModel,INotifyPropertyChanged
{
private string textboxsaf;
public string Textboxsaf
{
get { return textboxsaf; }
set {
textboxsaf = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Textboxsaf"));
}
}
private ICommand connectionCommand;
public ICommand ConnectionCommand
{
get { return connectionCommand; }
set { connectionCommand = value; }
}
public DialogViewModel()
{
ConnectionCommand = new RelayCommand(new Action<object>(SetValue));
}
public event PropertyChangedEventHandler PropertyChanged;
public void SetValue(object test)
{
textboxsaf= "ValueFromPopUpWindo";
Application.Current.Windows[1].Close();
}
}
ChildWindow.xaml
<Grid>
<Label x:Name="label" Content="my popup window" HorizontalAlignment="Left" Margin="73,68,0,0" VerticalAlignment="Top" Width="132"/>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="73,121,0,0"
TextWrapping="Wrap"
Text="{Binding Path=Textboxsaf,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left"
Margin="109,177,0,0" VerticalAlignment="Top" Width="75"
Command="{Binding Path=ConnectionCommand }"
/>
</Grid>
</Window>
MainWindow.xaml
<Grid>
<Button Name="btnConnectionString" Grid.Row="0" Grid.Column="2" Content="Connection string" Height="40" Width="150"
Command="{Binding Path=BuildConnectionCommand}"
DataContext="{Binding tfs}"></Button>
</Grid>
主窗口文件的代码隐藏 MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel()
{
rel = new ReleaseViewModel(),
tfs = new FunctionalViewModel(new WindowService()),
wnd = new DialogViewModel()
};
}
}
public class WindowService : IWindowService
{
public void OpenDialogWindow(DialogViewModel vm)
{
ConnectionWindow win = new ConnectionWindow();
win.DataContext = vm;
win.Show();
}
}
问题
我想从父视图模型(功能视图模型(访问子视图模型(对话视图模型(中属性文本框saf的值。将Textboxsaf的值从 funcitonalviewModel 分配给ConnectionString。关闭窗口后很好。
我不会在PropertyChanged
来检索DialogViewModel.Textboxsaf
的值,因为这个属性在对话框的生命周期内可能会多次更改。
我会IWindowService.OpenDialogWindow
返回自定义DialogResult
对象或原始DialogViewModel
可能会将IWindowService.OpenDialogWindow
转换为异步方法。
或者,实现IWindowService.DialogClosed
事件:
功能视图模型.cs
public class FunctionalViewModel : INotifyPropertyChanged
{
private readonly IWindowService _windowService;
private string connectionString;
public string ConnectionString
{
get { return connectionString; }
set
{
connectionString = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.ConnectionString)));
}
}
private void BuildConnectionString(object obj)
{
MessageBox.Show("will open a window");
_windowService.DialogClosed += OnDialogClosed;
_windowService.OpenDialogWindow(new DialogViewModel());
}
private void OnDialogClosed(object sender, DialogResultEventArgs e)
{
_windowService.DialogClosed -= OnDialogClosed;
ConnectionString = e.Result.Textboxsaf;
}
}
窗口服务.cs
public class WindowService : IWindowService
{
public event EventHandler<DialogResultEventArgs> DialogClosed;
public void OpenDialogWindow(DialogViewModel vm)
{
ConnectionWindow win = new ConnectionWindow();
win.DataContext = vm;
win.Closed += OnConnectionWindowClosed;
win.Show();
}
protected virtual void OnConnectionWindowClosed(object sender, EventArgs e)
{
var dialog = sender as FrameworkElement;
this.DialogClosed?.Invoke(this, new DialogResultEventArgs(dialog.DataContext as DialogViewModel));
}
}
DialogResultEventArgs.cs
public class DialogResultEventArgs : EventArgs
{
public DialogViewModel Result { get; }
public DialogResultEventArgs(DialogViewModel result) => this.Result = result;
}
您可以保留对DialogViewModel
的引用并订阅其PropertyChanged
事件:
private void BuildConnectionString(object obj)
{
var childViewModel = new DialogViewModel();
childViewModel.PropertyChanged += OnChildPropertyChanged;
MessageBox.Show("will open a window");
_windowService.OpenDialogWindow(childViewModel);
}
private void OnChildPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(DialogViewModel.Textboxsaf))
{
childViewModel.PropertyChanged -= OnChildPropertyChanged;
ConnectionString = (sender as DialogViewModel)?.DialogViewModel;
}
}