【问题标题】:ReactiveUI: Return value from a custom dialogReactiveUI:从自定义对话框返回值
【发布时间】:2017-12-06 18:09:09
【问题描述】:

我有一个窗口,它使用 ReactiveUI 交互打开第二个窗口作为模式对话框,然后从第二个窗口中的 ListBox 返回数据。

问题是当 .ShowDialog() 完成时,ViewModel 的 SelectedItem 总是计算为 null。我已经确认绑定工作正常,并且所选项目在对话框窗口的 ViewModel 中得到正确更新。只有当我返回到交互时,该属性才会重置为其默认值(null)。

我在这里整理了一个最小的问题示例:

https://github.com/replicaJunction/ReactiveDialogTest

主要被测逻辑在MainWindowViewModel.cs中。

编辑:这是代码中的一个 sn-p 基本思想:

GetNumberFromDialog = new Interaction<Unit, int>();
GetNumberFromDialog.RegisterHandler(interaction =>
{
    var vm = new DialogWindowViewModel();

    // Get a reference to the view for this VM
    var view = Locator.Current.GetService<IViewFor<DialogWindowViewModel>>();

    // Set its VM to our current reference
    view.ViewModel = vm;

    var window = view as Window;
    var dialogResult = window.ShowDialog();

    // At this point, vm.SelectedNumber is expected be the number the user selected -
    // but instead, it always evaluates to 0.

    if (true == dialogResult)
        interaction.SetOutput(vm.SelectedNumber);
    else
        interaction.SetOutput(-1);
});

OpenDialog = ReactiveCommand.Create(() =>
{
    GetNumberFromDialog.Handle(Unit.Default)
        .Where(retVal => -1 != retVal) // If the dialog did not return true, don't update
        .Subscribe(retVal =>
        {
            this.MyNumber = retVal;
        });
});

重现问题的步骤:

  1. 运行项目。请注意带有 -5000 的标签 - 这是要更新的数字。
  2. 单击“打开对话框”按钮。将打开一个对话窗口。
  3. 在列表框中选择一个数字。请注意,“当前选择”下的标签会更新 - 这与 ListBox.SelectedItem 绑定到相同的值。
  4. 单击确定。对话框关闭。

预期行为:主窗口中“我的号码是”下方的标签应更新为您在 ListBox 中选择的值。

实际行为:标签更新为 0(int 的默认值)。

为什么我的 ViewModel 在对话框关闭时会自行重置?

【问题讨论】:

    标签: c# wpf mvvm reactiveui


    【解决方案1】:

    查看 GitHub 上的示例有助于发现问题。你的DialogWindow 看起来像这样:

    public partial class DialogWindow : Window, IViewFor<DialogWindowViewModel>
    {
        public DialogWindow()
        {
            InitializeComponent();
            this.ViewModel = new DialogWindowViewModel();
            this.DataContext = this.ViewModel;
    
            this.ViewModel
                .WhenAnyValue(x => x.DialogResult)
                .Where(x => null != x)
                .Subscribe(val =>
                {
                    this.DialogResult = val;
                    this.Close();
                });
        }
    
        public DialogWindowViewModel ViewModel { get; set; }
        object IViewFor.ViewModel
        {
            get => ViewModel;
            set => ViewModel = (DialogWindowViewModel)value;
        }
    }
    

    MainWindowViewModel 中,将DialogWindow.ViewModel 属性设置为DialogWindowViewModel 实例。问题出现在此时。您的问题是设置 DialogWindow.ViewModel 属性确实 not 设置视图的 DataContext 或重新创建 WhenAnyValue 可观察对象。这意味着视图仍然绑定到DialogWindowViewModel(在DialogWindow 构造函数中创建的实例)的old 实例上的SelectedNumber 属性。要修复上面的示例代码,您可以简单地避免设置 ViewModel 属性,并使用对话框中已经设置的 ViewModel:

    GetNumberFromDialog.RegisterHandler(interaction =>
    {
        // Get a reference to the view for this VM
        var view = Locator.Current.GetService<IViewFor<DialogWindowViewModel>>();
    
        var window = view as Window;
        var dialogResult = window.ShowDialog();
    
        // use the ViewModel here that's already set on the DialogWindow
        if (true == dialogResult)
            interaction.SetOutput(view.ViewModel.SelectedNumber);
        else
            interaction.SetOutput(-1);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-29
      • 2014-02-14
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多