ListBox selectedItem工作但设置不在MVVM中工作

时间:2013-05-14 07:20:45

标签: c# wpf mvvm listbox

我正在研究WPF应用程序并关注MVVM。在我看来,有一个包含不同列的网格视图。其中一列是ListBox。现在的问题是,对于ListBox列,SelectedItem get工作正常但设置不了。

这是我的查看代码

<DataGrid ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" SelectionMode="Single">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
        <DataGridTemplateColumn Header="Actions">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

在我的ViewModel中,我有Main ViewModel类,其中包含Items列表。 Item类包含名称,操作列表和选定的操作。

public class MyViewModel : INotifyOfPropertyChanged
{
    private ObservableCollection<Item> _items;
    public ObservableCollection<Item> Items
    {
        get { return _items?? (_items= new ObservableCollection<Item>); }
    }

    private Item _selectedItem;
    public Item SelectedItem
    {
        get { return _selectedItem; }
        set { _selectedItem= value; }
    }
}

public class Item : INotifyOfPropertyChanged
{
    public string Name;

    private ObservableCollection<string> _actions;
    public ObservableCollection<string> Actions
    {
        get { return _actions?? (_actions= new ObservableCollection<string>); }
    }

    private string _selectedAction;
    public string SelectedAction
    {
        get { return _selectedAction; }
        set { _selectedAction = value; }
    }
}

Now SelectedItem for Items列表工作正常。但是SelectedItem为动作提供的Item类并不完全有效。我在SelectedAction的getter和setter上插入了断点。得到断点命中。但是如果我从UI中选择一个动作,那么为SelectedAction设置断点并不会被击中。

问题是什么。

View

当我选择Archive Project或Restore Project时,SelectedAction的setter不会被调用。

注意:我删除了不必要的信息,例如在列表中加载数据,实现INotifyOfPropertyChanged等。

7 个答案:

答案 0 :(得分:8)

我不知道是不是你的情况,但既然你说你已经删除了一些信息,我会尽力回答。

当我将一个custum模板添加到ListBox或ListView并且ListBoxItem中的控件处理click事件时,这种情况发生在我身上。

例如,如果您有这样的单选按钮

<ListBox ItemsSource="{Binding List}" SelectedItem="{Binding item}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Name}" GroupName="groupName">
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

当您实际点击单选按钮时,将不会设置SelectedItem,因为单选按钮将处理单击事件并且不会将其冒泡,因此ListBox可能会更改它的选择。

您必须确保ListBox获取事件,并且模板中的控件会相应地做出反应。在这种情况下,你将不得不做这样的事情。

<ListBox ItemsSource="{Binding List}" SelectedItem="{Binding Item}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <RadioButton Content="{Binding Name}" IsHitTestVisible="False">
        <RadioButton.Style>
          <Style TargetType="{x:Type RadioButton}">
            <Setter Property="IsChecked" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
          </Style>
        </RadioButton.Style>
      </RadioButton>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

答案 1 :(得分:3)

您需要在SelectedItem上指定TwoWay-Binding。否则,在UI上进行的更改未传递给您的viewmodel。

SelectedItem="{Binding SelectedAction, Mode=TwoWay}"

答案 2 :(得分:2)

当setter更改其值时,MyViewModel类的SelectedItem属性不会通过引发PropertyChanged事件来使用INotifyPropertyChanged接口:

public Item SelectedItem
{
    get { return _selectedItem; }
    set 
    {
        if(value != _selectedItem)
        {
            _selectedItem= value; 
            OnPropertyChanged("SelectedItem");
        }
    }
}

您应该对所有ViewModel中的所有属性执行此操作。

答案 3 :(得分:1)

这是修复。我们需要为selectedItem的列表框设置UpdateSourceTrigger,

<DataTemplate>
   <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>

答案 4 :(得分:0)

我不知道我是不是正确的方式,但你是否尝试将你的字符串包装在课堂上?

public class Item : INotifyOfPropertyChanged
{
public string Name;

private ObservableCollection<MyActionString> _actions;
public ObservableCollection<MyActionString> Actions
{
    get { return _actions?? (_actions= new ObservableCollection<MyActionString>); }
}

private MyActionString _selectedAction;
public MyActionString SelectedAction
{
    get { return _selectedAction; }
    set { _selectedAction = value; }
}
}

答案 5 :(得分:0)

查看VS中的输出窗口。可能您的房产类型与项目类型不同。

答案 6 :(得分:0)

不仅是&#34; Erno de Weerd&#34;回答正确,您需要通知所选属性的属性更改,但WPF DataGrid也是Microsoft提供的与MVVM相关的最多错误控件。

只有在更改外部列表的选择时,才会注意到内部列表的SelectedItem属性将更新。要在内部列表选择更改时刷新它,您需要更改列表上的绑定以添加:

SelectedItem =&#34; {Binding SelectedAction, UpdateSourceTrigger = PropertyChanged }&#34;

当列表框未嵌入数据网格列时,不需要这样做。