WPF / Silverlight:当命令参数改变时,如何进行Button调用ICommand.CanExecute?

时间:2010-07-18 22:41:41

标签: wpf silverlight

如果更改命令参数,如何进行按钮调用ICommand.CanExecute?

这是我目前的XAML。

<Button Content="Delete" Command="{Binding DeleteItemCommand}" CommandParameter="{Binding SelectedItem, ElementName=DaGrid}" />

编辑看起来这只是WPF中的一个问题。

3 个答案:

答案 0 :(得分:4)

我不确定你做错了什么,但这里有一个Button由BindingParameter和CanExecute Flag控制的例子。也许您的绑定参数不是DependencyProperty,因此,当它更改时,Button不会被通知。

<UserControl x:Class="SilverlightICommandTest.MainPage"
         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:ct="clr-namespace:SilverlightICommandTest"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
    <ct:TestModel x:Key="Model" />
</UserControl.Resources>

<StackPanel x:Name="LayoutRoot" Orientation="Vertical" Background="White" DataContext="{StaticResource Model}">
    <CheckBox Content="Enable" IsChecked="{Binding TestCmd.CanDoCommand, Mode=TwoWay}" />
    <Grid HorizontalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Text="{Binding ElementName=testSlider, Path=Value}" Width="40" Grid.Column="0" />
        <Slider Name="testSlider" Minimum="0" Maximum="100" SmallChange="1" Grid.Column="1" />
    </Grid>
    <Button Command="{Binding TestCmd}" CommandParameter="{Binding ElementName=testSlider, Path=Value}" Content="Do Something" />
</StackPanel>
</UserControl>

代码文件:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SilverlightICommandTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }

    public class TestModel : DependencyObject
    {
        TestCommand _testCmd = new TestCommand();

        public TestCommand TestCmd { get { return _testCmd; } }

        public TestModel()
        {
        }
    }

    public class TestCommand : DependencyObject, ICommand
    {
        public static readonly DependencyProperty CanDoCommandProperty = DependencyProperty.Register("CanDoCommand", typeof(Boolean), typeof(TestCommand), new PropertyMetadata(false, new PropertyChangedCallback(CanDoCommandChanged)));

        public Boolean CanDoCommand
        {
            get { return (Boolean)GetValue(CanDoCommandProperty); }
            set { SetValue(CanDoCommandProperty, value); }
        }

        public event EventHandler CanExecuteChanged;

        public TestCommand()
        {
        }

        public Boolean CanExecute(Object parameter)
        {
            return this.CanDoCommand && (((Int32)(Double)parameter) % 2 == 0);
        }

        public void Execute(Object parameter)
        {
            MessageBox.Show("Oh Hai!");
        }

        private void OnCanDoCommandChanged(DependencyPropertyChangedEventArgs args)
        {
            if (this.CanExecuteChanged != null)
            {
                this.CanExecuteChanged(this, new EventArgs());
            }
        }

        private static void CanDoCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            ((TestCommand)sender).OnCanDoCommandChanged(args);
        }
    }
}

将来我建议先对模式进行一些研究(http://www.silverlightshow.net/items/Model-View-ViewModel-in-Silverlight.aspx),如果仍然无法解决,请发布更多源代码。

答案 1 :(得分:1)

奇怪。通常,OnCommandParameterChanged调用UpdateCanExecute(两种内部方法)。 Binding to CommandParameter是否按预期工作?

答案 2 :(得分:1)

您需要致电CommandManager.InvalidateRequerySuggested重新评估CanExecute。请注意,它将为所有命令重新评估它,而不仅仅是您想要的那个......