【问题标题】:MVVM EventToCommandMVVM 事件到命令
【发布时间】:2012-10-30 11:16:57
【问题描述】:

嗨朋友们, 我正在开发 MVVM WPF 应用程序,我需要为 TelerikRadTab 控制 SelectionChanged 事件执行事件,我知道使用 MVVM 灯很简单EventToCommand 行为,但由于我使用的是 MVVM 框架(Link) 我必须使用建议的交互触发器 @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>

当我构建应用程序时,出现以下错误。

XML 命名空间“Link”中不存在属性“EventName”。

对此的任何建议或帮助都会有很大帮助。

【问题讨论】:

  • 只是为了确保您的包含是 xmlns:i 和 not xmlns:I(大写 I),如上所示,对吧?
  • 我也有类似的问题。对我来说,问题已解决,只安装 mvvm 库而不是整个包。

标签: mvvm eventtocommand


【解决方案1】:

我正在使用 mvvm light,但不需要经常使用事件命令功能。我以稍微不同的方式管理了与您相同的功能:

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

所以在主窗口视图模型上,我有一组视图模型,每个选项卡式项目一个,我将其绑定为控件的项目源。 然后我将选定项绑定到主视图模型上的一个属性。然后在该属性的设置器中,我可以执行我在 SelectionChangedEvent 中需要执行的任何特定操作。 在我的情况下,选项卡的视图模型是根据用户启动的内容动态加载的,并且每个视图模型都可能完全不同,因此它们都继承自一个公共基类,尽管您也可以使用接口。 因此,该集合是该 bas 类的 ObservableCollection,并且 selectedItem 绑定到的 ActiveTabbedViewModel 属性也是该类型。

可能适合也可能不适合您的场景,但通过使用这种方法,我不需要任何交互触发器

编辑:更详细一点 - 恐怕我不知道有一个博客可以指点你,所以将更多地解释一下我是如何处理这个的

所以 MainPage.xaml 带有 TabControl 和内容框架。 MainPageViewModel 是主页的视图模型。它有一个名为 TabbedViewModels 的属性,它是 TabbedWindowViewModelBase 的 ObservableCollection(我为此目的创建的一个类)

        /// <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,因为这会引发 propertychanged 事件,它将自动刷新绑定并显示与新选项卡相关的数据。您最初可以使用子视图模型上的 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 继承数据上下文 - 因此您有两个选择 - 您可以在 TabbedWindoViewModel 上拥有一个 DataViewModel 属性,并通过 ActiveTabbedWindow.DataViewModel 将所有内容绑定到该属性。或者,像我们一样,在主视图模型上为每个子视图模型设置一个属性并直接绑定到该属性:

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

希望这会有所帮助...

【讨论】:

  • 您好 SteveL,感谢您的回复,并感谢您的回复,我正在为 RadTabControl 使用用户控件,并且我的选项卡是静态的,即所有选项卡都预先定义了其中的控件,并且在选择更改时,它们必须从xml 文件。虽然我发现其他替代方案在某种程度上觉得不合适,但如果您能分享一个链接/博客作为您的处理方式,我将不胜感激。
  • 没有任何链接/博客,所以在上面展开。我完成此操作的场景相当复杂,即我有动态数据驱动的选项卡,然后是基于选项卡相关类型的菜单项列表,然后每个菜单项导航到新页面。我试图将其简化为听起来更接近您的场景,但可能忽略了一些东西......如果有任何需要澄清的地方,请告诉我
猜你喜欢
  • 2014-11-06
  • 1970-01-01
  • 2013-11-09
  • 2012-06-17
  • 1970-01-01
  • 2011-06-28
  • 2011-09-02
  • 2010-12-21
  • 2014-10-21
相关资源
最近更新 更多