简体   繁体   English

如何将按钮绑定到列表框项目

[英]How to bind button to Listbox item

ViewModel 视图模型

  public class MainWindowViewModel:BindableBase
  {
     public IRelayCommand MyCommand { get; protected set; }


    private void CreateCommand()
    {

        this.MyCommand = new RelayCommand(MyCommandExecuted, CanExecuteMyCommand);
    }

    private void MyCommandExecuted(object obj)
    {
        MessageBox.Show("Command Executed");
    }

    private bool CanExecuteMyCommand(object obj)
    {
        return true; // The value is based on Selected Item
    }
  }

XAML XAML

     <ListBox
             x:Name="myListBox" 
             ItemsSource="{Binding Path=MyClass}"
             <ListBox.ItemTemplate>
        <DataTemplate>
                <Expander Header="{Binding Path=HeaderName}" IsExpanded="True">
                    <StackPanel>
                        <DataGrid
                             x:Name="dataGrid"

                             AutoGenerateColumns="False"
                             ItemsSource="{Binding Path=RowVal}"  SelectedItem="{Binding CurrentItem}"/>
                    </StackPanel>
                </Expander>
        </DataTemplate>
        </ListBox.ItemTemplate>

<Button Content="Select" 

            Command="{Binding Path=MyCommand }" 
            CommandParameter="{Binding ElementName=myListBox,Path=SelectedItem}"/>

DataClass 数据类

  public class DataClass 
   {
    public string HeaderName { get; set; }
    public object RowVal { get; set; }
    public ObservableCollection<DataGridColumn> ColumnCollection { get; set;}
    private object currentItem;

    public object CurrentItem
    {
        get
        {
            return currentItem;
        }
        set
        {
            currentItem = value;

        }
    }

}

How can I bind my button to Listbox item which is CurrentItem in DataClass ? 如何将按钮绑定到DataClass中的CurrentItem的列表框项目?

I created a complete example to show how I would do it. 我创建了一个完整的示例来说明如何实现。 You would have to bind the parent element to SelectedItem as well, to keep track of when that item changes. 您还必须将父元素绑定到SelectedItem ,以跟踪该项目的更改时间。 Since the SelectedItem is public in your child class as well you can access that when your command triggers in your main view model. 由于SelectedItem在子类中也是公共的,因此您可以在命令在主视图模型中触发时访问它。

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition />
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Parents}" SelectedItem="{Binding SelectedParent}">
    <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type local:Parent}">
            <DataGrid ItemsSource="{Binding Children}" SelectedItem="{Binding SelectedChild}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
<Button Grid.Row="1" Width="70" Content="Click me" Height="25" Command="{Binding MyCommand}" />

ie in DoWork , you can get the child from the parent via its public property. 即在DoWork ,您可以通过其公共财产从父母那里获得孩子。

public sealed class WindowViewModel : INotifyPropertyChanged
{
    private readonly ObservableCollection<Parent> parents;
    private readonly ICommand myCommand;
    private Parent selectedParent;

    public WindowViewModel()
    {
        parents = new ObservableCollection<Parent>
        {
            new Parent{ Name = "P1"},
            new Parent{ Name = "P2"}
        };
        myCommand = new DelegateCommand(DoWork);
    }

    private void DoWork()
    {
        var selectedChild = SelectedParent == null ? null : SelectedParent.SelectedChild;

    }

    public Parent SelectedParent
    {
        get { return selectedParent; }
        set
        {
            if (selectedParent == value)
                return;
            selectedParent = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Parent> Parents
    {
        get { return parents; }
    }

    public ICommand MyCommand
    {
        get { return myCommand; }
    }

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

With the basic setup of Data models 通过数据模型的基本设置

public class Parent : INotifyPropertyChanged
{
    private ObservableCollection<Child> children;
    private Child m_SelectedChild;


    public Parent()
    {
        children = new ObservableCollection<Child>
        {
            new Child {Name = "C1"},
            new Child {Name = "C2"}
        };
    }

    public string Name { get; set; }

    public ObservableCollection<Child> Children
    {
        get { return children; }
    }

    public Child SelectedChild
    {
        get { return m_SelectedChild; }
        set
        {
            if (m_SelectedChild == value)
                return;
            m_SelectedChild = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Child
{
    public string Name { get; set; }
}

Another solution, if you are more interested of the Child item in your WindowViewModel is to change the relative source of where the binding should occur, in your DataGrid. 如果您对WindowViewModel中的Child项更感兴趣,另一种解决方案是在DataGrid中更改绑定发生位置的相对源。 ie, the binding would look like this instead: 即,绑定看起来像这样:

<DataGrid ItemsSource="{Binding Children}"
          SelectedItem="{Binding DataContext.SelectedChild, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" />

and then move the Property from Parent to WindowViewModel . 然后将属性从Parent移动到WindowViewModel With that you would be able to trigger changes to your button command when the child element changes for any of the Parent elements. 这样,当子元素更改为任何父元素时,您将能够触发对按钮命令的更改。

I think you want to pass the CurrentItem to the MyCommand as CommandParameter right? 我想您想将CurrentItem作为CommandParameter传递给MyCommand吗?

Then you only have to: 然后,您只需要:

CommandParameter="{Binding CurrentItem, UpdateSourceTrigger=PropertyChanged}"

尝试这个 :

    CommandParameter="{Binding ElementName=myListBox,Path=SelectedItem.CurrentItem}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM