【问题标题】:Nested UserControl event doesn't work with EventTrigger/InvokeCommandAction in MVVM/WPF scenario嵌套的 UserControl 事件不适用于 MVVM/WPF 场景中的 EventTrigger/InvokeCommandAction
【发布时间】:2018-11-22 14:09:49
【问题描述】:

我正在使用带有 Prism (MVVM) 的 WPF,并尝试为一些类构建一个检查器。其中一个类是 Vector3:

<Grid x:Name="Vector3Root" Background="White">
    <StackPanel Orientation="Horizontal">
        <StackPanel Orientation="Horizontal">
            <xctk:DoubleUpDown Tag="X" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding X}" ValueChanged="Vector3ValueChanged"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <xctk:DoubleUpDown Tag="Y" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding Y}" ValueChanged="Vector3ValueChanged"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <xctk:DoubleUpDown Tag="Z" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding Z}" ValueChanged="Vector3ValueChanged"/>
        </StackPanel>
    </StackPanel>
</Grid>

以及它的代码隐藏

namespace SimROV.WPF.Views{
public partial class Vector3View : UserControl
{
    public Vector3View()
    {
        InitializeComponent();
    }

    public static readonly RoutedEvent SettingConfirmedEvent =
        EventManager.RegisterRoutedEvent("SettingConfirmed", RoutingStrategy.Bubble,
        typeof(RoutedEventHandler), typeof(Vector3View));

    public event RoutedEventHandler SettingConfirmed
    {
        add { AddHandler(SettingConfirmedEvent, value); }
        remove { RemoveHandler(SettingConfirmedEvent, value); }
    }

    public void Vector3ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        RaiseEvent(new RoutedEventArgs(SettingConfirmedEvent));
    }
}}

我正在努力解决的问题是,我无法在另一个使用 Vector3ViewUserControl 的 ViewModel 上捕获任何触发的事件(ValueChangedSettingConfirmed):

<UserControl
         x:Class="SimROV.WPF.Views.TransformView"
         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:views="clr-namespace:SimROV.WPF.Views"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
         xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
         xmlns:prism="http://prismlibrary.com/"

mc:Ignorable="d" >

<Grid x:Name="TransformRoot" Background="White">
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Position" Margin="5"/>
            <!--<ContentPresenter ContentTemplate="{StaticResource Vector3Template}"/>-->
            <views:Vector3View x:Name="PositionVector3">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SettingConfirmed">
                        <prism:InvokeCommandAction Command="{Binding PositionValueChangedCommand}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </views:Vector3View>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Rotation" Margin="5"/>
            <!--<ContentPresenter ContentTemplate="{StaticResource Vector3Template}"/>-->
            <views:Vector3View x:Name="RotationVector3" SettingConfirmed="RotationValueChangedEvent"/>
        </StackPanel>
    </StackPanel>
</Grid>

此时我可以在代码隐藏中使用RotationValueChangedEvent 捕获SettingConfirmed,但由于我遵循MVVM 模式,这对我不起作用,这就是我使用EventTrigger 和@ 的原因987654331@ 在TransformViewModel 上捕获这些事件,但这些事件永远不会被解雇。 这是TransformViewModel

namespace SimROV.WPF.ViewModels{
public class TransformViewModel : BindableBase
{
    private ICommand _positionCommand;

    public ICommand PositionValueChangedCommand => this._positionCommand ?? (this._positionCommand = new DelegateCommand(PositionChanged));
    private void PositionChanged()
    {

    }
    public TransformViewModel()
    {

    }
}}

PositionChanged 永远不会被解雇,我完全不明白为什么。

我不知道这是否相关,但 Transform 是另一个 ViewModel 上 ObservableCollection&lt;IComponent&gt; 的一个元素,它由带有 ItemContainerStyleListView 呈现,它有一个带有 ContentPresenterContentPresenter ContentTemplateSelector 里面。

有人能指出为什么会发生这种情况以及如何解决吗?

谢谢。

【问题讨论】:

  • Vector3View 的 DataContext 是什么?可能不是 TransformViewModel。
  • 刚刚意识到我确实忘记将 prism:ViewModelLocator.AutoWireViewModel="True" 添加到 TransformView 和 Vector3View 中,但这并没有产生任何新的东西。事实上,Vector3 就像许多不同类中的一个属性,所以我不能将它硬编码为 Transform。是否可以从另一个 UserControl 以编程方式设置其 DataContext?
  • 设置 也没有什么不同
  • 为什么要将 UserControl 的 DataContext 设置为自身?您需要将其设置为 TransformViewModel 的实例,以便绑定到命令才能工作。
  • 真的很抱歉!我对 WPF/Prism 还是新手,因此有这种愚蠢的错误。在 TransformView.xaml.cs 将 PositionVector3.DataContext 设置为 this.DataContext 解决了我的问题。非常感谢您的帮助!

标签: c# wpf events mvvm prism


【解决方案1】:

如果Vector3ViewDataContext 实际上是TransformViewModel,那么您的EventTriggerInvokeCommandAction 应该可以正常工作,因此与PositionValueChangedCommand 属性的绑定成功。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2013-06-23
    相关资源
    最近更新 更多