WPF按钮动态命令

时间:2014-11-24 01:14:44

标签: c# wpf

我的WPF表单设置如下;

<ListBox x:Name="lbModules" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Button Command="{Binding OnClick}">
                <StackPanel>
                    <Image Source="{Binding ModuleIcon}"/>
                    <Label Content="{Binding ModuleName}"/>
                </StackPanel>
            </Button>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel></WrapPanel>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

在后面的代码中,lbModules被赋予List<ModuleButton>作为ItemsSource,其中ModuleButton定义如下;

internal class ModuleButton
{
    public ImageSource ModuleIcon {get; set;}
    public string ModuleName {get; set;}
    public ICommand OnClick {get; set;}
}

我的问题是以动态方式定义OnClick命令。我需要这样做,因为我正在使用MEF,而OnClick事件在技术上是在不同的程序集中。我只需要致电module.GetForm(),但似乎并不那么简单......

我按如下方式构建ModuleButton;

Lazy<IModule, IModuleMetadata> moduleCopy = module;
ModuleButton button = new ModuleButton
{
    ModuleName = moduleCopy.Metadata.ModuleName,
    ModuleIcon = 
        Imaging.CreateBitmapSourceFromHBitmap(moduleCopy.Value.ModuleButtonIcon.GetHbitmap(),
            IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()),
    OnClick = // TODO: Somehow call moduleCopy.Value.GetForm()
};

我一直在广泛搜索,在Google查看各种结果,this是我最新的来源之一。

我可以做我想做的事吗?如果是这样,怎么样?

1 个答案:

答案 0 :(得分:3)

好的,试试我的版本,因为Patrick的答案没有实现ICommand's CanExecuteChanged event,所以你不能顺利编译;此外,这个RelayCommand已经超载,只需要一个参数 - CanExecute始终返回true - 使其更易于使用。

摘自MSDN杂志文章WPF Apps With The Model-View-ViewModel Design Pattern

public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

OnClick = new RelayCommand ((o) => 
    {
        moduleCopy.Value.GetForm();
    });