【问题标题】:In WPF MVVM on button click how to have my view do something before or after the Command reference to the view model?在 WPF MVVM on button 单击如何让我的视图在命令引用视图模型之前或之后执行某些操作?
【发布时间】:2014-07-28 13:52:16
【问题描述】:

在一个表单上,我有一个标签和一个编辑按钮。单击编辑按钮时,标签的控件模板将更改为显示文本框和保存按钮。该保存按钮与视图模型上的保存命令相关联。

我的问题/问题是,当单击“保存”按钮时,我希望它在视图模型上执行命令之前或之后将控件模板更改回标签。在我的特殊情况下,除了正在执行的命令之外,只要单击“保存”按钮,它需要做的就是将我的标签上的一个属性设置为 True。

conv:ReadOnlyControlTemplate.DoLock="True"

更新 多亏了下面答案中的一些反馈,我现在离我更近了。我使用以下保存按钮:

<i:Interaction.Triggers>
                                        <ei:DataTrigger Comparison="Equal" Binding="{Binding Test, Converter={StaticResource TestConverter}, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Value="CommandUpdated"  >
                                            <ei:ChangePropertyAction  PropertyName="conv:ReadOnlyControlTemplate.DoLock" Value="True" TargetObject="{Binding ElementName=ShiftManagerMessages}" /> 
                                        </ei:DataTrigger>
                                    </i:Interaction.Triggers>

从 ei:ChangePropertyAction 的 TargetName 更改为 TargetObject 导致它正确地看到标签。但是现在我收到以下错误:

{"在类型 \"Label\" 上找不到名为 \"conv:ReadOnlyControlTemplate.DoLock\" 的属性。"}

我可以将它指向其他属性,但不是这个,我不明白为什么?

【问题讨论】:

  • 我无法指向该属性,因为它是附加属性。

标签: c# wpf mvvm binding


【解决方案1】:

使用DataTrigger控制模板的例子:

<UserControl x:Class="NextPlc.Instore.Epos.Till.UserControl1"
         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:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <ControlTemplate TargetType="Label" x:Key="ReadOnlyTemplate"></ControlTemplate>
    <ControlTemplate TargetType="Label" x:Key="EditTemplate"></ControlTemplate>
</UserControl.Resources>
<i:Interaction.Triggers>
    <ei:DataTrigger Binding="{Binding IsReadOnly}" Value="True">
        <ei:DataTrigger.Actions>
            <ei:ChangePropertyAction TargetName="label" PropertyName="Template" Value="{StaticResource ReadOnlyTemplate}"/>
        </ei:DataTrigger.Actions>
    </ei:DataTrigger>
    <ei:DataTrigger Binding="{Binding IsReadOnly}" Value="False">
        <ei:DataTrigger.Actions>
            <ei:ChangePropertyAction TargetName="label" PropertyName="Template" Value="{StaticResource EditTemplate}"/>
        </ei:DataTrigger.Actions>
    </ei:DataTrigger>
</i:Interaction.Triggers>
<Grid>
    <Label x:Name="label">
    </Label>
</Grid>

【讨论】:

    【解决方案2】:

    代码隐藏是一种选择,但请考虑如果您的命令失败该怎么办。如果那里有 ViewModel,则可以使用绑定到属性的数据触发器或模板选择器。

    我上周发布了一个关于如何编写数据模板选择器并将控件绑定到它的答案...Change View with its ViewModel based on a ViewModel Property

    使用 DataTrigger 执行此操作 - 添加对 Microsoft.Expressions.Interactions 的引用,然后添加 XAML...

    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
    

    在您的命名空间中,然后...

    <i:Interaction.Triggers>
        <ei:DataTrigger Binding="{Binding ViewModel.State}" Value="CommandUpdated">
             <Setter Property="Foreground" Value="Red" />
        </ei:DataTrigger>
    </i:Interaction.Triggers>
    

    这通过基于视图模型中的“状态”属性触发来工作。在这种情况下,state 是一个枚举,其中 CommandUpdated 是该枚举的一个值——它可以很容易地是一个 bool 或 int。

    【讨论】:

    • i:Interaction.Triggers 来自哪个命名空间?我尝试添加: xmlns:i="schemas.microsoft.com/expression/2010/interactivity" 但它不喜欢它。
    • 对不起,它很困惑并给我带来了错误的错误,清理后修复。它实际上抱怨的是 Setter Tag,它说它需要一个 TriggerAction。
    • 看起来它期待 Setter 标签所在的 TriggerAction。我可以在将要构建的位置使用 。但是,它似乎在运行时没有做任何事情。我需要做任何额外的事情来引用自定义属性吗?
    • 我还在 ei:DataTrigger 绑定中添加了一个 TestConverter,以确保正确设置和获取该值。只是 ei:ChangePropertyAction 没有做任何事情。你知道为什么吗?
    【解决方案3】:

    不确定我的问题是否正确,但您可以通过订阅按钮的各种(预览)mousedown 事件并在此处更改布局,在视图中运行一些代码。也就是说,如果您反对在 MVVM 项目中使用代码。然后,您的按钮将触发 VM 中的命令处理程序和视图中的事件处理程序。

    <Button MouseDown="Button_MouseDown" Command="{Binding SaveCommand}" />
    
     private void Button_MouseDown(object sender, System.Windows.RoutedEventArgs e)
     {
        // Set your property
     }
    

    【讨论】:

    • 我根本没有发现这种情况。在按钮上定义单击有效地取代了根本没有运行的命令。删除 Click 属性导致命令正常运行。
    • 您可以选择从点击事件执行命令:var btn = sender as Button; btn.Command.Execute(btn.CommandParameter);
    • 唯一的问题是 btn.Command 将为空。无论出于何种原因,您都看不到在 XAML 中设置的命令。
    猜你喜欢
    • 1970-01-01
    • 2023-01-28
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 2020-07-13
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多