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>());
}
}
Надеюсь это поможет...