【问题标题】:Looks like Interaction.Triggers doesn't work with DataContext set看起来 Interaction.Triggers 不适用于 DataContext 集
【发布时间】:2016-02-18 00:12:07
【问题描述】:

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

  1. MainWindow.xaml(我的观点)
  2. FooUserControl.xaml(我的用户控件的视图)
  3. MainWindowViewModel.cs(我的视图的视图模型)

基本上就是这样。很简单。代码如下:

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 连接应该是 11 的规则吗?一个视图 - 一个 ViewModel?

【问题讨论】:

  • 您有什么理由不只是通过使用代码隐藏作为模型来使控件具体化?是否有一些要求您必须分离模型,或者您是否打算让它们在相同的视觉或其他东西上可替换?具体控件更简单、更易于使用,并消除了您在此处看到的许多麻烦,不知道为什么这么多工程师试图使 MVVM 过于复杂。

标签: c# .net wpf xaml mvvm


【解决方案1】:

如果您想为您的local:FooUserControl 分配一个新的DatContext,您可以这样做,但您将无法再从直接MainWindowViewModel。您必须将您的Binding 更改为Command,如下所示:

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

当我们设置控件的DataContext 时,它会自动传递 到它的子控件Property Value Inheritance。而如果 你将UserControlDataContext 更改为a hierarchy/VisualTree 对于Ancestors,DataContext 将有所不同 和Descendants

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 2013-08-04
    相关资源
    最近更新 更多