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

时间:2015-03-04 08:08:31

标签: c# wpf mvvm

视图模型

  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

     <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}"/>

数据类

  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;

        }
    }

}

如何将我的按钮绑定到DataClass中的CurrentItem的Listbox项目?

3 个答案:

答案 0 :(得分:1)

我创建了一个完整的例子来展示我将如何做到这一点。您还必须将父元素绑定到SelectedItem,以跟踪该项目何时更改。由于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}" />

即。在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));
    }
}

使用数据模型的基本设置

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; }
}

另一个解决方案是,如果您对WindowViewModel中的Child项更感兴趣,请在DataGrid中更改绑定应该发生的位置的相对来源。即绑定看起来像这样:

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

然后将该属性从Parent移至WindowViewModel。这样,当子元素更改为任何父元素时,您将能够触发对按钮命令的更改。

答案 1 :(得分:0)

我想你想将CurrentItem作为CommandParameter传递给MyCommand吗?

然后你只需要:

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

答案 2 :(得分:0)

试试这个:

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