命令执行时按钮不会被禁用

发布于 2024-10-08 12:09:28 字数 11369 浏览 0 评论 0原文

我喜欢 MVVM Light 框架,正如很多人所说,简单但功能强大。

我正在尝试禁用一个按钮,执行与 EventToCommand 示例中相同的操作(工作正常,但有针对性或 3.5)。我添加了一个 IsEnabled 事件,正在触发。

我的程序目标是4.0。

我的命令被禁用了,但按钮保持启用状态。

我也在我的程序中添加了一个事件,但没有触发。

不知道我错过了什么。

我的Xaml:

<Window x:Class="MyWPFApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
    xmlns:vw="clr-namespace:MyWPFApp.Views"

    Title="MainWindow"
    Height="300"
    Width="300"
    SizeToContent="WidthAndHeight"
    DataContext="{Binding Source={StaticResource Locator}, Path=v_MainWindow}">

<Window.Resources>
    <!--<ResourceDictionary x:Key="ResDict">
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Skins/MainSkin.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>-->
    <ControlTemplate x:Key="ButtonTemplate"
                     TargetType="Button">
        <Grid x:Name="Root"
              Opacity="0.8"
              RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <TransformGroup>
                    <ScaleTransform />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                </TransformGroup>
            </Grid.RenderTransform>

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualStateGroup.Transitions>
                        <VisualTransition From="MouseOver"
                                          GeneratedDuration="00:00:00.2000000"
                                          To="Normal" />
                        <VisualTransition From="Normal"
                                          GeneratedDuration="00:00:00.2000000"
                                          To="MouseOver" />
                    </VisualStateGroup.Transitions>
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="1" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Pressed">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="1" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.9" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.9" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Disabled">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.4" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Rectangle Fill="{TemplateBinding Background}"
                       Stroke="Black"
                       RadiusX="8"
                       RadiusY="8" />
            <TextBlock HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="{TemplateBinding Content}"
                       TextWrapping="Wrap"
                       FontSize="12"
                       FontWeight="Bold" />
        </Grid>
    </ControlTemplate>

    <Style x:Key="ButtonStyle"
           TargetType="Button">
        <Setter Property="Template"
                Value="{StaticResource ButtonTemplate}" />
        <Setter Property="Cursor"
                Value="Hand" />
    </Style>

</Window.Resources>

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Row="0"  Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Left">
        <Button Content="Change to Error Status" Style="{StaticResource ButtonStyle}" IsEnabledChanged="EnableChanged">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmd:EventToCommand Command="{Binding StatusCommand}"
                                   CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Content}" MustToggleIsEnabled="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Change to Warning" Style="{StaticResource ButtonStyle}" IsEnabledChanged="EnableChanged">              
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmd:EventToCommand Command="{Binding StatusCommand}"
                                       CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Content}" MustToggleIsEnabled="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Success" IsEnabled="False"/>
        <Button Content="Info"/>
    </StackPanel>
    <TextBlock Grid.Row="0"  Grid.Column="1"
               FontSize="36"
               FontWeight="Bold"
               Foreground="Purple"
               Text="{Binding Welcome}"
               VerticalAlignment="Center"
               HorizontalAlignment="Center"
               TextWrapping="Wrap">
       <!--<i:Interaction.Triggers>
           <i:EventTrigger EventName="MouseEnter">
               <cmd:EventToCommand Command="{Binding StatusCommand}"
                                   CommandParameter="Error" />
           </i:EventTrigger>
       </i:Interaction.Triggers>-->
    </TextBlock>
    <vw:v_StatusBar Grid.Row="1" Grid.ColumnSpan="2" />

</Grid>

我在视图模型中的代码

using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;



namespace MyWPFApp.ViewModel
{
/// <summary>
/// This class contains properties that the main View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm/getstarted
/// </para>
/// </summary>
public class vm_MainWindow : ViewModelBase
{
    public string Welcome
    {
        get
        {
            return "Welcome to Geert's WPF template (based on MVVM Light)";
        }
    }

    private string _status = "Initialized...";

    public string Status
    {
        get
        {
            return _status;
        }

        private set
        {
            if (_status == value)
            {
                MessageBox.Show("Status is already " + value);
                return;
            }

            _status = value;

            MessageBox.Show("Setting status to " + _status);
            Messenger.Default.Send<string>(value, "StatusChange");

        }
    }

    public RelayCommand<string> StatusCommand
    {
        get;
        private set;
    }


    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public vm_MainWindow()
    {
        if (IsInDesignMode)
        {
            // Code runs in Blend --> create design time data.
        }
        else
        {
            // Code runs "for real"

            StatusCommand = new RelayCommand<string>(p => Status = string.Format("{0}", p), p => p != _status);

        }
    }

    ////public override void Cleanup()
    ////{
    ////    // Clean up if needed

    ////    base.Cleanup();
    ////}
}

}

I like the MVVM Light framework, as many said, simple but powerful.

I am trying to disable a button, does same thing as in EventToCommand sample (working allright, but targeted or 3.5). I added an IsEnabled event, is firing.

My program is targeted for 4.0.

my command is disabled allright, but the button stays enabled.

I have added an event in my program too, is not firing.

don't know what I am missing.

my Xaml:

<Window x:Class="MyWPFApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
    xmlns:vw="clr-namespace:MyWPFApp.Views"

    Title="MainWindow"
    Height="300"
    Width="300"
    SizeToContent="WidthAndHeight"
    DataContext="{Binding Source={StaticResource Locator}, Path=v_MainWindow}">

<Window.Resources>
    <!--<ResourceDictionary x:Key="ResDict">
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Skins/MainSkin.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>-->
    <ControlTemplate x:Key="ButtonTemplate"
                     TargetType="Button">
        <Grid x:Name="Root"
              Opacity="0.8"
              RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <TransformGroup>
                    <ScaleTransform />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                </TransformGroup>
            </Grid.RenderTransform>

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualStateGroup.Transitions>
                        <VisualTransition From="MouseOver"
                                          GeneratedDuration="00:00:00.2000000"
                                          To="Normal" />
                        <VisualTransition From="Normal"
                                          GeneratedDuration="00:00:00.2000000"
                                          To="MouseOver" />
                    </VisualStateGroup.Transitions>
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="1" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Pressed">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="1" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.9" />
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.9" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Disabled">
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Duration="00:00:00.0010000"
                                                           Storyboard.TargetName="Root"
                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                      Value="0.4" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Rectangle Fill="{TemplateBinding Background}"
                       Stroke="Black"
                       RadiusX="8"
                       RadiusY="8" />
            <TextBlock HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="{TemplateBinding Content}"
                       TextWrapping="Wrap"
                       FontSize="12"
                       FontWeight="Bold" />
        </Grid>
    </ControlTemplate>

    <Style x:Key="ButtonStyle"
           TargetType="Button">
        <Setter Property="Template"
                Value="{StaticResource ButtonTemplate}" />
        <Setter Property="Cursor"
                Value="Hand" />
    </Style>

</Window.Resources>

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Row="0"  Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Left">
        <Button Content="Change to Error Status" Style="{StaticResource ButtonStyle}" IsEnabledChanged="EnableChanged">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmd:EventToCommand Command="{Binding StatusCommand}"
                                   CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Content}" MustToggleIsEnabled="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Change to Warning" Style="{StaticResource ButtonStyle}" IsEnabledChanged="EnableChanged">              
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmd:EventToCommand Command="{Binding StatusCommand}"
                                       CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Content}" MustToggleIsEnabled="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Success" IsEnabled="False"/>
        <Button Content="Info"/>
    </StackPanel>
    <TextBlock Grid.Row="0"  Grid.Column="1"
               FontSize="36"
               FontWeight="Bold"
               Foreground="Purple"
               Text="{Binding Welcome}"
               VerticalAlignment="Center"
               HorizontalAlignment="Center"
               TextWrapping="Wrap">
       <!--<i:Interaction.Triggers>
           <i:EventTrigger EventName="MouseEnter">
               <cmd:EventToCommand Command="{Binding StatusCommand}"
                                   CommandParameter="Error" />
           </i:EventTrigger>
       </i:Interaction.Triggers>-->
    </TextBlock>
    <vw:v_StatusBar Grid.Row="1" Grid.ColumnSpan="2" />

</Grid>

MY code in viewmodel

using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;



namespace MyWPFApp.ViewModel
{
/// <summary>
/// This class contains properties that the main View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm/getstarted
/// </para>
/// </summary>
public class vm_MainWindow : ViewModelBase
{
    public string Welcome
    {
        get
        {
            return "Welcome to Geert's WPF template (based on MVVM Light)";
        }
    }

    private string _status = "Initialized...";

    public string Status
    {
        get
        {
            return _status;
        }

        private set
        {
            if (_status == value)
            {
                MessageBox.Show("Status is already " + value);
                return;
            }

            _status = value;

            MessageBox.Show("Setting status to " + _status);
            Messenger.Default.Send<string>(value, "StatusChange");

        }
    }

    public RelayCommand<string> StatusCommand
    {
        get;
        private set;
    }


    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public vm_MainWindow()
    {
        if (IsInDesignMode)
        {
            // Code runs in Blend --> create design time data.
        }
        else
        {
            // Code runs "for real"

            StatusCommand = new RelayCommand<string>(p => Status = string.Format("{0}", p), p => p != _status);

        }
    }

    ////public override void Cleanup()
    ////{
    ////    // Clean up if needed

    ////    base.Cleanup();
    ////}
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

软糖 2024-10-15 12:09:28

发现问题了,CanExecuteChanged 简单从来没有触发!!!!!!

首先,我(在中继命令中)添加了注释中建议的内容:
http://msdn.microsoft.com/query/dev10.query?appId= Dev10IDEF1&l=EN-US&k=k(SYSTEM.WINDOWS.INPUT.COMMANDMANAGER.REQUERYSUGGESTED);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22);k(DevLang-CSHARP)&rd =true

然后我注意到只有最后一个按钮被启用/禁用。

再次合乎逻辑的是,relaycommand 中添加的每个处理程序都会覆盖前一个处理程序。

因此,我在 eventtocommand 中添加了事件处理支持。

并且,一切正常。

会将我的更正发送给 Buignon 先生,希望他能检查并正式发布。

ps 仅针对 WPF 4.0 检查和更改(我现在唯一需要的东西)

Found the problem, CanExecuteChanged simple never fired!!!!!!

first, I added (in relaycommand) what is suggested in the remarks here:
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.WINDOWS.INPUT.COMMANDMANAGER.REQUERYSUGGESTED);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22);k(DevLang-CSHARP)&rd=true

Then I noticed that only the last button was enabled/disabled.

again logical, every handler added in relaycommand overwrote the previous one.

so, I added event handling support in eventtocommand.

and, everything is wokring fine.

will send my corrections to Mr Buignon hoping that he will check and release officially.

ps only checked and changed for WPF 4.0 (only thing i need now)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文