In WPF MVVM on button click how to have my view do something before or after the Command reference to the view model?

余生长醉 提交于 2019-12-14 03:19:53

问题


On one form I have a Label and an Edit Button. When the Edit Button is clicked the control template for the label changes to show a TextBox and a Save Button. That Save Button is tied to a Save Command on the View Model.

My question / problem is, when the Save button is clicked I want it to change the control template back to being a label either before or after the Command Executes on the View Model. In my particular case all it needs to do is set a property on my label to True whenever the Save Button is Clicked in addition to the command being executed.

conv:ReadOnlyControlTemplate.DoLock="True"

UPDATE I am much closer now thanks to some of the feedback in answers below. I am using the following for the Save Button:

<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>

Changing to TargetObject from TargetName of the ei:ChangePropertyAction caused it to see the Label correctly. However now I get the following error:

{"Cannot find a property named \"conv:ReadOnlyControlTemplate.DoLock\" on type \"Label\"."}

I can point it to other properties, just not this one and I don't understand why?


回答1:


An example of using DataTrigger to control template:

<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:


Code behind is an option, but consider what to do if your command fails. If you've got a ViewModel there, you can use a data trigger or template selector bound to a property.

I posted an answer last week about how to write a data template selector and bind a control to it... Change View with its ViewModel based on a ViewModel Property

Doing this with a DataTrigger - add a reference to Microsoft.Expressions.Interactions, then add the XAML...

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

in your namespace, then...

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

This works by triggering based on a property 'State' in the viewmodel. In this case state is an Enumeration where CommandUpdated is a value of that enum - it could as easily be a bool or int.




回答3:


Not sure if I got the problem correct, but you can run some code behind in your view by subscribing to various (preview)mousedown events of your button and change your layout there. That is, if you have nth against using code behind in an MVVM project. Your button will than trigger both the command handler in your VM, and event handler in your view.

<Button MouseDown="Button_MouseDown" Command="{Binding SaveCommand}" />

 private void Button_MouseDown(object sender, System.Windows.RoutedEventArgs e)
 {
    // Set your property
 }


来源:https://stackoverflow.com/questions/24996817/in-wpf-mvvm-on-button-click-how-to-have-my-view-do-something-before-or-after-the

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!