看起来Interaction.Triggers不适用于DataContext集

时间:2016-02-18 00:12:07

标签: c# .net wpf xaml mvvm

我将从我的代码开始(整个示例在这里:https://github.com/robertwojnar/MvvmDemo1) 在我的小演示中,我有一个带有usercontrol的单一视图应用程序。所以我有:

  1. MainWindow.xaml(我的观点)
  2. FooUserControl.xaml(我的usercontrol视图)
  3. MainWindowViewModel.cs(我的视图的视图模型)
  4. 基本上就是这样。非常简单。这是代码:

    FooUserControl.xaml

        <UserControl x:Class="MvvmDemo1.WPF.Views.FooUserControl"
                     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                     xmlns:local="clr-namespace:MvvmDemo1.WPF.Views"
                     mc:Ignorable="d" 
                     d:DesignHeight="100" d:DesignWidth="100">
            <Grid MouseDown="UIElement_OnMouseDown">
                <Rectangle Fill="BlueViolet" />
            </Grid>
        </UserControl>
    

    FooUserControl(代码隐藏)

        public partial class FooUserControl : UserControl
        {
            public FooUserControl()
            {
                InitializeComponent();
            }   
    
            public event EventHandler<BarEventArgs> BarClick;
            private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
            {
                double x = e.GetPosition(this).X;
                double y = e.GetPosition(this).Y;
                string value_to_pass = "[" + x + "," + y + "]"; 
    
                BarEventArgs bar = new BarEventArgs() { Bar = 2, Foo = value_to_pass };
                BarClick?.Invoke(sender, bar);
            }
        }
    

    MainWindow.xaml (没有代码)

        <Window x:Class="MvvmDemo1.WPF.Views.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:local="clr-namespace:MvvmDemo1.WPF.Views"
                mc:Ignorable="d"
                Title="MainWindow" Height="300" Width="300"
                xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                xmlns:cmd="http://www.galasoft.ch/mvvmlight"
                xmlns:viewModels="clr-namespace:MvvmDemo1.WPF.ViewModels">
            <Window.DataContext>
                <viewModels:MainWindowViewModel />
            </Window.DataContext>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Loaded">
                    <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=LoadedCommand}" PassEventArgsToCommand="True" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Grid>
                <local:FooUserControl>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="BarClick">
                            <cmd:EventToCommand Command="{Binding ClickedCommand}" PassEventArgsToCommand="True" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </local:FooUserControl>
            </Grid>
        </Window>
    

    MainWindowViewModel.cs

        public class MainWindowViewModel : ObservableObject
        {
            public string Title => "Main window";
    
            public ICommand LoadedCommand => new RelayCommand(Loaded);
            private void Loaded()
            {
                Debug.WriteLine("Loaded");
            }   
    
            public ICommand ClickedCommand => new RelayCommand<BarEventArgs>(o => Clicked(o.Foo));
            private void Clicked(string a)
            {
                Debug.WriteLine("Clicked " + a);
            }
        }
    

    正如您所看到的,应用程序只是一个紫色矩形(在点击事件中)将点击坐标发送到MainWindowViewModel(通过ICommand,使用MVVM Light的EventToCommandInteraction.Triggers)。

    这是我的问题和疑问:

    我想为UserControl添加一个ViewModel。想要将FooUserControlViewModel添加到FooUserControl的DataContext。当我设置FooUserControl的DataContext时,问题是 ClickedCommand没有被触发。问题是为什么?

    当您克隆我的repo并将FooUserControl(代码隐藏)构造函数更改为此时,您将明白我的观点:

        public FooUserControl()
        {
            InitializeComponent();
            DataContext = new FooUserControlViewModel();
        }
    

    修改 看起来,MainWindowViewModel被分配给FooUserControl的DataContext(我想,因为Iteraction.TriggersEventToCommand)。为什么会这样?这是否违反了view-viewmodel连接应为1&lt; - &gt; 1的规则。一个视图 - 一个ViewModel?

1 个答案:

答案 0 :(得分:1)

如果 您想为DatContext分配一个新的local:FooUserControl,那么您可以这样做,但您将无法再直接绑定MainWindowViewModel的控件。您必须更改Binding下面的Command:<{1}}:

<cmd:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}},Path=DataContext.ClickedCommand}" PassEventArgsToCommand="True" />
  

当我们设置控件的DataContext时,它将以原始方式显示   通过Property Value Inheritance进行儿童控制。而如果   您在中间更改DataContext的{​​{1}}   层次结构/ VisualTree,UserControl的DataContext将不同   和Ancestors

也没有这样的规则1 View -1 ViewModel。这完全取决于您的设计的复杂性/要求您必须为Descendants设置ViewModels,为不同的View设置一个ViewModel