MVVM EventToCommand

Привет, друзья, я разрабатываю приложение MVVM WPF, мне нужно выполнить событие для события TelerikRadTab Control SelectionChanged, я знаю, что с использованием MVVM light это просто с использованием поведения EventToCommand, но, поскольку я использую инфраструктуру MVVM ( ссылка), мне нужно использовать Предлагаемые триггеры взаимодействия @ Link.

Для ниже я добавил ссылку DLL интерактивности от

C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\Silverlight\v4.0

и в XAML я включил

xmlns:I="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity



<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
     <Command:ChangePropertyOnTarget
          Target="{Binding}" PropertyName="SelectedItems"
          Value="{Binding SelectedItems, ElementName=ItemsToChoose}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>

Когда я создаю приложение, я получаю ошибку ниже.

Свойство EventName не существует в пространстве имен XML Link.

Любое предложение или помощь по этому вопросу было бы очень полезно.

1 ответ

Я использую mvvm light, но мне не нужно часто использовать событие для управления функцией. Я управлял той же функциональностью, что и вы, немного по-другому:

<telerik:RadTabControl Template="{StaticResource TabControlTemplate}" 
                ItemsSource="{Binding TabbedViewModels }" SelectedItem="{Binding ActiveTabbedViewModel, Mode=TwoWay}"
                ItemTemplate="{StaticResource TabItemTemplate}" Style="{StaticResource RadTabControlStyleBorderless}" />

так что в модели окна основных окон у меня есть коллекция моделей представления, по одному на элемент с вкладками, которые я связываю как источник элемента элемента управления. Затем я связываю выбранный элемент со свойством в модели основного вида. Затем в установщике этого свойства я могу сделать что-то конкретное, что мне потребовалось бы сделать в SelectionChangedEvent. В моем случае модели представления для вкладок динамически загружаются в зависимости от того, что инициировал пользователь, и каждая из них потенциально сильно отличается, поэтому все они наследуются от общего базового класса, хотя вы также можете использовать интерфейс. коллекция, таким образом, является ObservableCollection этого базового класса, и свойство ActiveTabbedViewModel, к которому привязывается selectedItem, также принадлежит к этому типу.

Может или не может быть подходящим для вашего сценария, но при использовании этого подхода мне не нужны никакие триггеры взаимодействия

РЕДАКТИРОВАТЬ: вдаваясь в некоторые подробности - боюсь, я не знаю ни одного блога, на который можно было бы указать, поэтому расскажу немного подробнее о том, как я подошел к этому

Итак, MainPage.xaml с TabControl и фреймом контента. MainPageViewModel - модель представления для главной страницы. У него есть свойство с именем TabbedViewModels, которое представляет собой ObservableCollection объекта TabbedWindowViewModelBase (класс, который я создал для этой цели)

        /// <summary>
    /// Gets or sets a collection of TabbedViewModels - each one will be represented by a tab on the top bar of the main window
    /// </summary>
    public ObservableItemCollection<CastleTabbedWindowViewModelBase> TabbedViewModels
    {
        get
        {
            return this.tabbedViewModels;
        }

        set
        {
            this.tabbedViewModels = value;
            this.RaisePropertyChanged(() => this.TabbedViewModels);
        }
    }

        /// <summary>
    /// Gets or sets the Active Tab - is bound to the Tab bars SelectedItem - when changing to
    /// another tab / view model it sets the page menu item to the correct one for that view model
    /// </summary>
    public CastleTabbedWindowViewModelBase ActiveTabbedViewModel
    {
        get
        {
            return this.activeTabbedViewModel;
        }

        set
        {
            this.activeTabbedViewModel = value;
            this.RaisePropertyChanged(() => this.ActiveTabbedViewModel);

            if (value != null)
            {
                // when the active tab has changed want to ensure we open the previously opened page that the new tab was on
                value.DoSomething();
            }
        }
    }

На данный момент все зависит от того, насколько сложен ваш сценарий. Если у вас такое же представление, но вы просто меняете данные, оно может быть привязано к ActiveTabbedViewModel, поскольку при возникновении события, измененного свойством, автоматически обновляются привязки и отображаются данные, относящиеся к новой вкладке. Вы можете использовать DoSomething на дочерней модели представления для начальной загрузки его данных - вам нужно будет сделать это только один раз, если вы не хотите обновить его.

Из того, что вы описали, одним из способов было бы создать класс TabbedWindowViewModel ниже:`

public class TabbedWindowViewModel :ViewModelBase
{
    private RelayCommand<NavigationEventArgs> navigationCommand;

    /// <summary>
    /// Gets or sets the position /order that this tab item is relative to the other tab items
    /// </summary>
    public int MenuOrder { get; set; }

    /// <summary>
    /// Gets or sets the Navigation Id
    /// </summary>
    public int NavigationId { get; set; }

    /// <summary>
    /// Gets or sets the Title that will be displayed for this tab item
    /// </summary>
    public string Title { get; set; }

    /// <summary>
    /// Gets or sets the navigation target that will be navigated to when the tab item is clicked
    /// </summary>
    public string NavigationTarget { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether the tab item is enabled
    /// </summary>
    public bool IsEnabled { get; set; }

    /// <summary>
    /// Gets the command for regular navigation.
    /// </summary>
    public virtual ICommand NavigationCommand
    {
        get
        {
            return this.navigationCommand
                   ??
                   (this.navigationCommand =
                    new RelayCommand<NavigationEventArgs>(
                        this.ExecuteNavigationCommand, x => this.IsEnabled));
        }
    }

   public void DoSomething()
   {
       //do whatever you need to
       //then navigate to the correct page
       this.NavigationCommand.Execute(null);

   }

    private void ExecuteNavigationCommand(NavigationEventArgs e)
    {
        NavigationManager.NavigateToView(this.NavigationTarget);
    }


}

Обратите внимание, что NavigationManager является статическим вспомогательным классом для облегчения навигации. Тогда каждое из представлений, к которым вы потенциально можете перейти, унаследует текст данных от MainPage - и тогда у вас есть два варианта - вы можете иметь свойство DataViewModel для свойства TabbedWindoViewModel и связать все с этим через ActiveTabbedWindow.DataViewModel. Или, как у нас, есть свойство для каждой дочерней модели представления в модели основного представления и привязка непосредственно к этому свойству:

        public SummaryViewModel SummaryViewModel
    {
        get
        {
                  return this.summaryViewModel
                  ?? (this.summaryViewModel = (SummaryViewModel)ViewModelFactory.GetPageViewModel<SummaryViewModel>());
        }
    }

Надеюсь это поможет...

Другие вопросы по тегам