将RoutedEvent或RoutedCommand冒泡到ViewModel

时间:2009-08-13 20:19:49

标签: c# wpf mvvm prism routed-events

我有一个ViewModel集合,它们使用样式呈现为制表符,以提取要在选项卡上显示的相关内容:

public class TabViewModel : DependencyObject
{
      public object Content
      {
          get { return (object)GetValue(ContentProperty); }
          set
          {
              SetValue(ContentProperty, value);
          }
      }

}

这是TabControl:

<TabControl 
     ItemsSource={Binding MyCollectionOfTabViewModels}" 
     ItemContainerStyle="{StaticResource TabItemStyle}" />

这是风格

<Style TargetType="TabItem" x:Key="TabItemStyle">
     <Setter Property="Content" Value="{Binding Content}"/>
</Style>

我们正在创建一个usercontrol实例,并将TabViewModel的“Content”属性设置为该属性,以便user控件显示在TabItem的Content区域中。

MyCollectionOfViewModels.Add(new TabViewModel() 
{ 
     Content = new MyUserControl();
});

我的问题是,我想允许添加到TabViewModel的Content属性的MyUserControl(或其任何子控件)引发TabViewModel处理的事件

任何人都知道我会这样做吗?

我们已经尝试过使用RoutedEvents和RoutedCommands,但是无法让任何东西100%工作并让它与MVVM兼容。我真的认为这可以通过RoutedEvent或RoutedCommand完成,但我似乎无法使其工作。

注意:我已经删除了一些相关的Prism特定代码,但是如果你想知道我们为什么这么傻,那是因为我们试图通过使用Prism的RegionManager来保持控制不可知。

3 个答案:

答案 0 :(得分:2)

您可以向TabViewModel添加State属性,并检查DependencyPropertyChanged事件。

想象一下以下的枚举:

public enum TabViewModelState
{
    True,
    False,
    FileNotFound
}

然后将State属性添加到此枚举的TabViewModel:

public static readonly DependencyProperty StateProperty =
    DependencyProperty.Register("State", typeof(TabViewModelState), typeof(TabViewModel), new PropertyMetadata(OnStateChanged));

private static void OnStateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    TabViewModel viewModel= (TabViewModel)obj;

    //Do stuff with your viewModel
}

在控件中使用对此属性的双向绑定:

<CheckBox Checked="{Binding Path=State, Converter={StaticResource StateToBooleanConverter}, Mode=TwoWay}" />

最后但并非最不重要的是实现转换器,该转换器将转换为控件所需的原始值..(在我的示例中为boolean&lt; - &gt; TabViewModelState):

public class StateToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        TabViewModelState state = (TabViewModelState) value;
        return state == TabViewModelState.True;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool result = (bool) value;
        return result ? TabViewModelState.True : TabViewModelState.False;
    }
}

所以现在你有一个由UI管理的State属性,并在你需要响应时抛出已更改的事件。

希望这有帮助!

答案 1 :(得分:1)

如果你在ViewModel上放一个命令并且只是从你的UserControl绑定它,那么无论如何都会触发它。你不必冒泡它,UserControl只会找到命令并使用它。

如果您的ViewModel上有一个委托命令“GoCommand”,那么您的UserControls按钮绑定将如下所示:

<Button Command="{Binding GoCommand}" >Go</Button>

我经历了同样的思考过程,认为UserControl需要冒泡命令,但它不会 - 绑定只会在ViewModel上找到命令时自行挂起。

希望这会有所帮助,我不会错过这一点! ;)

答案 2 :(得分:1)

你应该看看Marlon Grech的Attached Command Behavior,它允许你将ViewModel命令附加到GUI事件。