Привязать представления DialogResult к свойству ViewModels?
Я относительно новичок в WPF, XAML и привязках данных. У меня есть вид (окно) и вид-модель.
Я попытался реализовать шаблон MVVM, который означает, что ни представление, ни модель представления не содержат ссылки друг на друга. Весь обмен данными происходит через привязки данных.
Пока все хорошо, но теперь я столкнулся с проблемой, для которой не могу найти решение.
На мой взгляд у меня есть кнопка Start, которая связана с командой.
<Button Command="{Binding NextCommand}" Content="Next">
NextCommand имеет тип ActionCommand : ICommand
В моем случае NextCommand просто вызывает закрытый метод внутри модели представления.
Проблема, которую я пока не могу найти, заключается в следующем:
Как закрыть окно в конце метода view-models NextCommandAction?
private void NextCommandAction(object o)
{
...
...
// close the window
}
Поскольку у меня нет ссылки на представление, я не могу просто установить DialogResult = true;
Единственное работающее решение, которое я нашел до сих пор, - это добавить скрытую радиокнопку в представление и связать ее значение со свойством CloseView и создать метод CloseView в файле xaml.cs, который связан с событием Checked скрытого радио. -кнопка. В этом методе я установил DialogResult = true;
Хотя это работает, я чувствую, что должно быть лучшее решение, чем добавление скрытых элементов к вашему виду!
Заранее спасибо за помощь!
PS: мне мой вопрос понятен. Если что-то неясно, не стесняйтесь спрашивать.
4 ответа
Вы можете передать ссылку на окно как CommandParameter команде Close и сделать все, что требуется для окна.
<Button Content="Close" Command="{Binding Path=CloseCommand}"
CommandParameter="{Binding ElementName=Window}"/>
private void CloseCommand(object sender)
{
Window wnd = sender as Window;
wnd.Close();
}
CommandParameter="{Binding ElementName=Window}" предполагает, что в вашем XAML есть элемент с именем "Window". например, ваш тег Window должен иметь имя Name="Window"
Этот вопрос был одним из первых, которые возникли, когда я погуглил, чтобы проверить, DialogResult
это свойство зависимости (это не так:-))
Добавьте свойство зависимости в ваше окно:
public static readonly DependencyProperty InteractionResultProperty =
DependencyProperty.Register(
nameof(InteractionResult),
typeof(Boolean?),
typeof(MyWpfWindow1),
new FrameworkPropertyMetadata(default(Boolean?),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnInteractionResultChanged));
public Boolean? InteractionResult
{
get => (Boolean?) GetValue(InteractionResultProperty);
set => SetValue(InteractionResultProperty, value);
}
private static void OnInteractionResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyWpfWindow1) d).DialogResult = e.NewValue as Boolean?;
}
Я назвал свое свойство I nteractionResult, хотя хорошее имя тоже сработало бы.
В xaml сразу после вы можете связать его со стилем
<Window.Style>
<Style TargetType="{x:Type z:MyWpfWindow1}">
<Setter Property="InteractionResult"
Value="{Binding UpdateResult}" />
</Style>
</Window.Style>
UpdateResult - это свойство в моей модели просмотра.
private Boolean? _updateResult;
public Boolean? UpdateResult
{
get => _updateResult;
set => SetValue(ref _updateResult, value);
}
Метод SetValue - это обычное свойство уведомления.
protected virtual Boolean SetValue<T>(ref T field, T value,
[CallerMemberName]String propertyName = null)
{
if (Equals(field, value))
return false;
field = value;
RaisePropertyChanged(propertyName);
return true;
}
и свойство устанавливается обычным образом
<Button Content="Cancel"
Command="{Binding CancelCommand}" />
ICommand CancelCommand { get; }
private void OnCancel()
{
UpdateResult = false;
}
Отказ от ответственности: работает на моем компьютере.
Вдохновленный ответом Чандрашекхара Джоши (но без использования имени элемента):
Определите CommandParameter в кнопке:
<Button
Command="{Binding CloseCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
Content="Close" />
Определить команду (и реализацию):
CloseCommand = new DelegateCommand<Window>((w) => w.DialogResult = true);