2015-12-07 2 views
4

Как открыть или закрыть новое окно в WPF без нарушения правил шаблона MVVM?
Я просто хочу подражать модулю входа в мс офис.Призматическое всплывающее окно в WPF

Я уже читал this article, но есть ошибка при переходе от параметра confirmation

Я в настоящее время с помощью призмы 5.0.

ответ

3

Update
Что заставило меня поставить еще один ответ был неумение применить принятый ответ на мой проект , который с помощью Prism 6,
но после сдачи оригинальный ответ (см это ниже) и обсуждение в комментариях я обнаружил, что основной проблемой было следующее: Призмы 6 изменили пространства имен некоторых классов, все классы, которые использовались в принятом ответе, все еще существуют в Призма 6, но в других библиотечных пространствах и пространствах имен
Итак, если вы используете Pris м 6, вы можете применить принятый ответ с этими изменениями

первой замены тех namesapces

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:pi="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity" 
xmlns:pit="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity" 

со следующими пространствами имен

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:prism="http://prismlibrary.com/" 

второй обновляют XAML как следующие

<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}"> 
    <i:Interaction.Triggers> 
     <prism:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" > 
      <prism:PopupWindowAction> 
       <prism:PopupWindowAction.WindowContent> 
        <views:CustomPopupView /> 
       </prism:PopupWindowAction.WindowContent> 
      </prism:PopupWindowAction> 
     </prism:InteractionRequestTrigger> 
    </i:Interaction.Triggers> 
</Button> 

ПРИМЕЧАНИЕ 1
Убедитесь, что вид, который вы используете (в приведенном выше примере <views:CustomPopupWindow>), не является окном или вы получите исключение.

Примечание 2
Эти изменения необходимы ТОЛЬКО в случае, если вы используете Prism 6. потому что (как я уже сказал в оригинальный ответ ниже), которые DLLs используемые принятым ответом является осуждается в Prism 6.

Примечание 3
Убедитесь, что вы обращаетесь к Prism.Wpf DLL, которые могут быть downloaded from Nuget.


Оригинал ответа
принял ответ направлен на Призма 5, он использует this library который осуждается в Prism 6.

На самом деле the article which you reference в вашем вопросе было очень полезно (по крайней мере, для меня), и это не сбой.

Я попробую обобщить эту статью.

ViewModel

public class ViewModel : BindableBase 
{ 
    public ViewModel() 
    { 
     _showWindowCommand = new DelegateCommand(ShowWindow); 
     _interactionRequest = new InteractionRequest<Confirmation>(); 
    } 

    private readonly DelegateCommand _showWindowCommand; 
    private InteractionRequest<Confirmation> _interactionRequest; 

    public ICommand ShowWindowCommand 
    { 
     get { return _showWindowCommand; } 
    } 

    public IInteractionRequest InteractionRequest 
    { 
     get { return _interactionRequest; } 
    } 

    private void ShowWindow() 
    { 
     _interactionRequest.Raise(
      new Confirmation(), 
      OnWindowClosed); 
    } 

    private void OnWindowClosed(Confirmation confirmation) 
    { 
     if (confirmation.Confirmed) 
     { 
      //perform the confirmed action... 
     } 
     else 
     { 

     } 
    } 
} 

XAML

<Button Command="{Binding ShowWindowCommand}" Content="Show Window" > 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Raised" SourceObject="{Binding InteractionRequest}"> 
      <i:EventTrigger.Actions> 
       <local:ShowWindowAction></local:ShowWindowAction> 
      </i:EventTrigger.Actions> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

и вам нужно будет использовать эти пространства имен

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:local="clr-namespace:The namespace which contains the ShowWindowAction"> 

Action Trigger

using System; 
using Prism.Interactivity.InteractionRequest; 
using System.Windows.Interactivity; 
using System.Windows; 

public class ShowWindowAction : TriggerAction<FrameworkElement> 
{ 
    protected override void Invoke(object parameter) 
    { 
     InteractionRequestedEventArgs args = parameter as InteractionRequestedEventArgs; 
     if (args != null) 
     { 
      Confirmation confirmation = args.Context as Confirmation; 
      if (confirmation != null) 
      { 
       // Replace ParametersWindow with your own window. 
       ParametersWindow window = new ParametersWindow(); 
       EventHandler closeHandler = null; 
       closeHandler = (sender, e) => 
       { 
        window.Closed -= closeHandler; 
        args.Callback(); 
       }; 
       window.Closed += closeHandler; 
       window.Show(); 
      } 
     } 
    } 
} 

Объяснение

  1. Вам нужно Prism.Core и Prism.Wpf DLLs (по крайней мере), чтобы сделать этот код работать. Метод InvokeShowWindowAction, который действительно отобразит окно.
  2. вы можете обработать закрытие окна в OnWindowClosed, которое мы передали ему как ответный вызов классу ShowWindowAction, и мы назвали его оттуда, когда окно действительно закрыто.
+0

В чем разница? 'PopupWindowAction' все еще присутствует в Prism 6 (https://github.com/PrismLibrary/Prism/blob/master/Source/Wpf/Prism.Wpf/Interactivity/PopupWindowAction.cs) и как' IConfirmation', так и 'Confirmation' классы все еще присутствуют в обеих структурах. За исключением того, что Prism5 был (на тот момент), который все еще поддерживается MS и Prims6, не находится в руках сообщества, ничего из использования классов не изменилось. Нет необходимости в собственном 'TriggerAction', за исключением случаев, когда вам нужно что-то, что' PopupWindowAction' не предлагает (т.е. ленивая загрузка, для которой я требовал новый просмотр и режим просмотра при каждом вызове) – Tseng

+0

@ Ценг да, вы правы, я думаю, что различия это пространства имен, классы все еще существуют, но пространства имен изменились. Кроме того, я просто предоставил другой способ, используя пользовательский 'ActionTrigger' *, возможно, это может быть полезно для других *, также я использую' i: EventTrigger' вместо 'InteractionRequestTrigger', но да, в общем, наши ответы очень близки друг к другу , –

+0

@Tseng см. Новое обновление для ответа. –

12

К счастью, Prism 5.0 (и я предполагаю, что 6.0 тоже не работал с ним), имеет класс InteractionRequest<T>, который вы можете использовать из кода для подбора запросов на взаимодействие.

Запрос взаимодействия - это в основном окно, которое запрашивает у пользователя определенное действие и вызывает обратный вызов (при необходимости или желательно) с решениями/действиями пользователей.

public class ShellViewModel : BindableBase 
{ 
    private readonly IRegionManager regionManager; 

    public ShellViewModel(IRegionManager regionManager) 
    { 
     if (regionManager == null) 
      throw new ArgumentNullException("regionManager"); 

     this.regionManager = regionManager; 
     this.OptionSettingConfirmationRequest = new InteractionRequest<IConfirmation>(); 

     openConnectionOptionsCommand = new DelegateCommand(RaiseConnectionOptionsRequest); 
    } 

    public InteractionRequest<IConfirmation> OptionSettingConfirmationRequest { get; private set; } 

    private readonly ICommand openConnectionOptionsCommand; 
    public ICommand OpenConnectionOptionsCommand { get { return openConnectionOptionsCommand; } } 

    private void RaiseConnectionOptionsRequest() 
    { 
     this.OptionSettingConfirmationRequest.Raise(new Confirmation { Title = "Options not saved. Do you wish to save?" }, OnConnectionOptionsResponse); 
    } 

    protected virtual void OnConnectionOptionsResponse(IConfirmation context) 
    { 
     if(context.Confirmed) 
     { 
      // save it 
     } 

     // otherwise do nothing 
    } 
} 

В XAML вы могли бы сделать что-то вроде

<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}"> 
    <i:Interaction.Triggers> 
     <pit:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" > 
      <pie:LazyPopupWindowAction RegionName="ConnectionSettings" 
           NavigationUri="ConnectionSettingsView" IsModal="True" /> 
     </pit:InteractionRequestTrigger> 
    </i:Interaction.Triggers> 
</Button> 

Я использовал свою собственную реализацию в PopupWindowAction (см страницы проекта GitHub для его реализации) называется LazyPopupWindowAction, которая будет экземпляр встроенного ConnectionSettingsView View на мыши. Если вам не нравится, что ваше представление создается только один раз, не стесняйтесь использовать PopupWindowAction, тогда он будет создан одновременно с представлением, содержащим действие.

Это в основном копия & пасты с разрезанием некоторых бесполезных линий из одного из моих проектов. Я использовал интерфейсы IConfirmation и INotification вместо конкретных реализаций.

XAML с PopupWindowAction

<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}"> 
    <i:Interaction.Triggers> 
     <pit:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" > 
      <pi:PopupWindowAction> 
       <pi:PopupWindowAction.WindowContent> 
        <views:CustomPopupView /> 
       </pi:PopupWindowAction.WindowContent> 
      </pi:PopupWindowAction> 
     </pit:InteractionRequestTrigger> 
    </i:Interaction.Triggers> 
</Button> 

объявлений пространств имен

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:pi="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity" 
xmlns:pit="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity" 
xmlns:pie="clr-namespace:MyProject.UI.Prism.Interactivity;assembly=MyProject.UI" 

Update: Поскольку люди продолжают спрашивать о LazyPopupWindowAction, я поместил источник в GitHub Gist. В основном он основан на PopupWindowAction от Prims 5 (и для Prism, не тестировал его с Prism 6, но, вероятно, не будет работать без настроек) и делает то же самое, но также добавляет поддержку Region and Navigation с помощью открытое окно, то, что мне нужно в моем приложении.

Одна вещь, которую мне не понравилась реализация по умолчанию, заключалась в том, что представление и его модель представления будут создаваться при одновременном создании экземпляра оболочки, а ViewModel остается в его состоянии, когда вы его закрываете (на самом деле это было просто скрыто) ,

+0

благодарю вас за предоставленную мне idea..regarding это ... СПАСИБО ВАМ БОЛЬШОЕ – Neil

+0

Согласно [** ссылке **] (https://www.nuget.org/packages/Prism.Interactivity) эта библиотека была * Устарела *, есть ли у вас какие-либо другие решения для Prism 6, спасибо. –

+0

Другое примечание: как вы устанавливаете «Label =» Options «' класса 'Button', для' Button' нет такого свойства. Вы имеете в виду «Content =» Options «' вместо этого? –

Смежные вопросы