我有一个窗口,它使用ReactiveUI Interaction打开第二个窗口作为模式对话框,然后在第二个窗口中从ListBox返回数据。
问题是当.ShowDialog()完成时,ViewModel的SelectedItem总是计算为null。我已经确认绑定工作正常,所选项目正在对话框窗口的ViewModel中正确更新。只有当我返回到Interaction时,属性才会重置为默认值(null)。
我在这里总结了一个问题的最小例子:
https://github.com/replicaJunction/ReactiveDialogTest
正在测试的主要逻辑是在MainWindowViewModel.cs。
编辑:这是代码中带有基本想法的片段:
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;
});
});
重现问题的步骤:
预期行为:主窗口中的标签&#34;我的号码是&#34;应更新为您在ListBox中选择的值。
实际行为:标签更新为0(int的默认值)。
为什么我的ViewModel会在对话框关闭时自行重置?
答案 0 :(得分:2)
在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
属性不设置视图DataContext
或重新创建WhenAnyValue
可观察对象。这意味着视图仍然绑定到SelectedNumber
的旧实例上的DialogWindowViewModel
属性(在DialogWindow
构造函数中创建的实例)。要修复上面的示例代码,您可以简单地避免设置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);
});