Привязать представления 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);
Другие вопросы по тегам