I am trying to access property value of a child window's view model from the parent View Model.I am calling window from parent view model.I want to make changes in main window based on the operation in child view model. I couldn't get any value of child view model in parent view model.I am trying this in MVVM pattern.
Interface for dialog
public interface IWindowService
{
void OpenDialogWindow(DialogViewModel vm);
}
Parent view model
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());
}
}
Child View Model
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>
Code behind file of main window 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();
}
}
Question
I would like to access the value of the property Textboxsaf in the child view model(DialogViewModel) from parent view model(FunctionalViewModel) . Assign value of Textboxsaf to ConnectionString from the funcitonalviewModel . after closing window is good.
I wouldn't use PropertyChanged
to retrieve the value of DialogViewModel.Textboxsaf
as this proprty might change multiple times during the lifetime of the dialog.
I would make IWindowService.OpenDialogWindow
return a custom DialogResult
object or the original DialogViewModel
probably converting the IWindowService.OpenDialogWindow
to an asynchronous method.
Alternatively implement a IWindowService.DialogClosed
event:
FunctionalViewModel.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;
}
}
WindowService.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;
}