访问按钮,单击Silverlight模板控件上ListBox DataTemplate中的按钮

| 我有一个Silverlight模板控件(不是用户控件),其中包含一个ListBox。 在列表框的数据模板中,我有一个按钮,如下所示:
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width=\"Auto\" />
                                        <ColumnDefinition Width=\"Auto\" />
                                        <ColumnDefinition Width=\"*\" />
                                    </Grid.ColumnDefinitions>
                                    <ProgressBar Grid.Column=\"0\" Width=\"70\" Height=\"20\" Value=\"{Binding Path=Percentage}\" Minimum=\"0.0\" Maximum=\"100.0\" />
                                    <TextBlock Grid.Column=\"0\" Text=\"{Binding Path=Percentage, StringFormat=\'{}{0:##0.0}%\'}\" Margin=\"10,3,3,3\" HorizontalAlignment=\"Center\" />
                                    <TextBlock Grid.Column=\"1\" Text=\"{Binding Path=File.Name}\" Margin=\"3\" />
                                    <Button Grid.Column=\"2\" Content=\"Remove\" x:Name=\"RemoveButton\" Command=\"{TemplateBinding DeleteCommand}\" Style=\"{TemplateBinding UploadButtonStyle}\" HorizontalAlignment=\"Right\" Margin=\"0,0,5,0\" />
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
看到模板末尾的按钮了吗?我如何访问它的点击事件?由于按钮是DataTemplate的一部分,因此我无法使用GetTemplateChild()方法。我已经尝试过指挥(如上所示)。尽管样板控件并非完全是MVVM,但看来这是要走的路。 有任何想法吗?也许除了指挥以外?否则我的命令做错了吗? 这是一些相关的代码: ...依赖属性/属性定义...(应该是Dep Prop吗?)
    public static readonly DependencyProperty DeleteCommandProperty =
        DependencyProperty.Register(\"DeleteCommand\", typeof(ICommand), typeof(MultipleFileUpload), new PropertyMetadata(null));

    public ICommand DeleteCommand
    {
        get { return (ICommand)GetValue(DeleteCommandProperty); }
        set 
        { 
            SetValue(DeleteCommandProperty, value);
            FirePropertyChanged(\"DeleteCommand\");  //INotifyPropertyChanged stuff
        }
    }
...在OnApplyTemplate()中...
    public override void OnApplyTemplate()
    {
        ....
        DeleteCommand = new DelegateCommand(RemoveItemFromList, CanRemove);
        ....
        base.OnApplyTemplate();
    }
ICommand动作
    private void RemoveItemFromList(object commandParameter)
    {
        //NEVER GETTING HERE!
    }
我希望它很小。 谢谢大家! 凯文     
已邀请:
我已将命令作为属性添加到我绑定到ListBoxes(和其他ItemsControl \)的ItemSource中的对象的类中。这确实意味着我必须更改我的\“ data \”对象以处理GUI事件-这通常看起来是错误的和骇人听闻的。 我还派生了ItemsControl(但由于列表框是ItemsControl,因此它可能仍然适用)。我将自己的属性添加到最终要从项目中访问的派生控件。您的情况是按钮命令处理程序。设置这些属性应该很容易,因为它们没有被锁定在该嵌套模板中。 接下来,我在该派生类中重写GetContainerForItemOverride()并返回另一个类,即我自己的派生ContentPresenter。这个新的ContentPresenter也应该具有相同的命令属性-构造它时,使其与GetContainerForItemOverride中ItemControl的命令相等。 现在,在DataTemplate中,使用TemplateBinding(而不是常规绑定)来获取该命令。 我已经开始尝试制作所有这些的通用/可重用版本。 编辑,基本示例:
class MyItemsControl : ItemsControl
{
   public Command MyCommand {get;set;} // I\'ve often use a full-blown DP here

snip

   protected override DependencyObject GetContainerForItemOverride()
   {
       return new MyContentPresenter(this.MyCommand); // MyContentPresenter is just a derived ContentPresenter with that same property.
   }
再次编辑: 我还将代码放在ItemsControl.PrepareContainerForItemOverride中。此方法为您提供ContentControl(如果要覆盖GetContainerForItemOverride,则为您自己的控件)和列表中的当前\“ Item \”。在这里,您还可以对ContentControl实例进行进一步的初始化-如果要执行的操作取决于绑定到该对象的对象。     
我建议您使用一个继电器命令:
public class RelayCommand<T> : ICommand
{
    #region Fields

    readonly Action<T> _execute = null;
    readonly Predicate<T> _canExecute = null;

    #endregion // Fields

    #region Constructors

    public RelayCommand(Action<T> 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<T> execute, Predicate<T> 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((T)parameter);
    }

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

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

    #endregion // ICommand Members
}
XAML:
<Button Grid.Column=\"2\" Content=\"Remove\" x:Name=\"RemoveButton\" Command=\"{Binding DeleteCommand}\" CommandParameter={Binding} Style=\"{TemplateBinding UploadButtonStyle}\" HorizontalAlignment=\"Right\" Margin=\"0,0,5,0\" />
每次单击按钮时,它将执行相同的delete命令,但会将当前项作为参数传递。 希望这可以帮助     
我已经在MSDN中遇到过这个想法,我没有尝试过,但是我觉得值得在这里分享: 列表框中的项目的DataContext与视图DataContext不同。每个项目的DataContext都引用了绑定到列表框的ItemsSource属性的集合中的一个项目。 一种解决方案是将command属性绑定到静态资源,并将静态资源的值设置为要绑定的命令。在以下来自Stock Trader RI的XAML中对此进行了说明。
<!--Specifying the observablecommand in the view\'s resources-->
<UserControl.Resources>
   <Infrastructure:ObservableCommand x:Key=\"BuyCommand\" />
</UserControl.Resources>

<!—Binding the Button Click to the command. This control can sit inside a datagrid or a   list box. -->
<Button Commands:Click.Command=\"{Binding Path=Value, Source={StaticResource BuyCommand}}\" Commands:Click.CommandParameter=\"{Binding Path=TickerSymbol}\" />
然后,在视图的代码背后,必须指定资源的值实际上指向表示模型上的命令。以下是来自Stock Trader RI的示例,其中将展示模型上的BuyCommand属性放入资源中。
((ObservableCommand)this.Resources[\"BuyCommand\"]).Value = value != null ? value.BuyCommand : null;
    
您好,您可以使用相对来源和AncesterType。然后它对我来说很好。 请参考以下代码。
<Button Content=\"Delete\"  Command=\"{Binding DataContext.DeleteCommand,
          RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}\"
          CommandParameter=\"{Binding Path=SelectedItem, RelativeSource= {RelativeSource FindAncestor, AncestorType=
                 {x:Type ListBox}}}\"/>
    

要回复问题请先登录注册