问题
I'm implementing code from the excellent answer to this question WPF + Castle Windsor + MVVM: Locator-DataContext. I'm not sure how to get the value from ShowDialog()
though without resorting to code behind (which breaks testability), anyone have any ideas?
I was using this class with the MVVM Light Messenger
class and it was working fine, but entails using the Service Locator anti-pattern.
EDIT
The current code I have that isn't working is
DataSourcePicker.xaml.cs
public DataSourcePicker(IDataSourcePickerViewModel viewModel)
{
InitializeComponent();
_viewModel = viewModel;
DataContext = viewModel;
Closed += (s, a) => RaiseDismissed();
}
public event Action OnDismissed;
private void RaiseDismissed()
{
if (OnDismissed != null)
OnDismissed()
}
in DataSourcePicker.xaml
<Button IsDefault="True" .../>
in MainViewModel.cs
public void NewDataSource()
{
var viewModel = _dspViewModelFactory.ResolveDataSourcePickerViewModel();
var view = _dspFactory.ResolveDataSourcePicker(viewModel);
view.OnDismissed += () => NewDataSourceImplementation(viewModel);
view.ShowDialog();
}
I need some way to set the IsAccepted property on the DataSourcePickerViewModel to true when the user clicks the button
回答1:
Because you have neglected to show your implementation of "ShowDialog" or explain how your DataSourcePicker
shows up in the application, it is difficult to give you a clear solution; So, here are two options depending on your implementation of DataSourcePicker
:
In the unlikely event that your DataSourcePicker.ShowDialog
method simply invokes MessageBox.Show
, your solution is simple.
public void NewDataSource()
{
var viewModel = _dspViewModelFactory.ResolveDataSourcePickerViewModel();
var view = _dspFactory.ResolveDataSourcePicker(viewModel);
var result = view.ShowDialog();
if (result.HasValue)
{
viewModel.IsAccepted = result.Value;
}
}
However, if you have implemented your DataSourcePicker
as a custom Modal dialog window, or you do not close the dialog window immediately after ShowDialog
has executed, the solution becomes more complex.
In this scenario, you will have to add an ICommand
to your viewmodel.
class DataSourcePickerViewModel : IDataSourcePickerViewModel
{
public bool IsAccepted { get; set; }
public ICommand NewDataSourceCommand { get; private set; }
public DataSourcePickerViewModel()
{
NewDataSourceCommand = new RelayCommand(() =>
{
IsAccepted = true;
});
}
}
Then, you will have to update your DataSourcePickerView
with:
<Button Command="{Binding NewDataSourceCommand}"
Content="Close"/>
Otherwise, you will need to Use one of the following solutions for binding commands to events:
- MVVM Light - EventToCommand
- MSDN - EventToCommand
- Marlon Grechs AttachedCommandBehavior
Then, you would update the view like so (If using the AttachedCommandBehavior library):
<ModalControl x:Class="_24318313.DataSourcePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:_24318313"
mc:Ignorable="d" d:DataContext="{d:DesignInstance local:DataSourcePickerViewModel}"
local:CommandBehavior.Event="Close"
local:CommandBehavior.Command="{Binding NewDataSourceCommand}"
d:DesignHeight="300" d:DesignWidth="300"/>
If you feel this doesn't solve you issue, please let me know and I will update in response to your feedback; Otherwise, please mark an answer as accepted.
来源:https://stackoverflow.com/questions/24318313/getting-result-from-showdialog-without-resorting-to-code-behind