无法从父视图模型 WPF MVVM 应用程序中的弹出 window 获取值

Unable to get values from pop up window in parent view model WPF MVVM application

我正在尝试从父视图访问 属性 子 window 的视图模型的值 Model.I 从父视图 model.I 调用 window =] 想根据子视图模型中的操作在主 window 中进行更改。我无法在父视图中获得子视图模型的任何值 model.I 我正在 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>

主文件背后的代码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();            
        }               
    }

问题

我想从父视图模型 (FunctionalViewModel) 访问子视图模型 (DialogViewModel) 中 属性 Textboxsaf 的值。将 Textboxsaf 的值从 funcitonalviewModel 分配给 ConnectionString。关闭后 window 很好。

您可以保留对 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;
    }
}

我不会使用 PropertyChanged 来检索 DialogViewModel.Textboxsaf 的值,因为此属性在对话框的生命周期内可能会更改多次。

我会让 IWindowService.OpenDialogWindow return 成为自定义 DialogResult 对象或原始 DialogViewModel 可能会将 IWindowService.OpenDialogWindow 转换为异步方法。

或者实施 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));
    }               
}

DialogResultEventArgs.cs

public class DialogResultEventArgs : EventArgs
{
    public DialogViewModel Result { get; }
          
    public DialogResultEventArgs(DialogViewModel result) => this.Result = result;
}