Estoy tratando de acceder al valor de propiedad del modelo de vista de una ventana secundaria desde el Modelo de vista principal. Estoy llamando a la ventana desde el modelo de vista principal. Deseo realizar cambios en la ventana principal en función de la operación en el modelo de vista secundaria. No pude obtener ningún valor del modelo de vista secundaria en el modelo de vista principal. Estoy intentando esto en el patrón MVVM.

Interfaz para el diálogo

 public interface IWindowService
{
    void OpenDialogWindow(DialogViewModel vm);
     
}

Modelo de vista principal

 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());                                  

        }
}

Modelo de vista secundaria

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>

Código detrás del archivo de la ventana principal 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();            
        }               
    }

Pregunta

Me gustaría acceder al valor de la propiedad Textboxsaf en el modelo de vista secundaria (DialogViewModel) desde el modelo de vista primaria (FunctionalViewModel). Asigne el valor de Textboxsaf a ConnectionString del funcitonalviewModel. Después de cerrar la ventana está bien.

1
sagar tech 25 jun. 2020 a las 16:47

2 respuestas

No usaría PropertyChanged para recuperar el valor de DialogViewModel.Textboxsaf ya que esta propiedad podría cambiar varias veces durante la vida útil del diálogo.

Haría que IWindowService.OpenDialogWindow devuelva un objeto DialogResult personalizado o el DialogViewModel original probablemente convirtiendo el IWindowService.OpenDialogWindow en un método asincrónico.

Alternativamente, implemente un evento IWindowService.DialogClosed:

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));
    }               
}

DialogResult EventArgs.vs

public class DialogResultEventArgs : EventArgs
{
    public DialogViewModel Result { get; }
          
    public DialogResultEventArgs(DialogViewModel result) => this.Result = result;
}
2
BionicCode 25 jun. 2020 a las 16:12

Puede mantener una referencia al DialogViewModel y suscribirse a su evento 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;
    }
}
2
mm8 25 jun. 2020 a las 15:10