9

我正在开发 WPF 应用程序并关注 MVVM。在我看来,有一个包含不同列的网格视图。其中一列是 ListBox。现在的问题是,对于 ListBox 列, SelectedItem 可以正常工作,但 set 不能。

这是我的查看代码

<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 类,其中包含一个项目列表。项目类包含名称、动作列表和选定动作。

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

现在,Items 列表的 SelectedItem 工作正常。但是 Actions 的 SelectedItem insde Item 类不能完全工作。我在 SelectedAction 的 getter 和 setter 上插入了断点。获得断点命中。但是,如果我从 UI 中选择一个操作,则不会为 SelectedAction 设置断点。

有什么问题。

看法

当我选择存档项目或恢复项目时,不会调用 SelectedAction 的设置器。

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

4

7 回答 7

9

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

当我将自定义模板添加到 ListBox 或 ListView 并且 ListBoxItem 中的控件自己处理单击事件时,这种情况发生在我身上。

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

<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>
于 2013-10-21T14:07:39.657 回答
4

您需要在 SelectedItem 上指定一个双向绑定。否则,在 UI 上所做的更改不会传递给您的视图模型。

SelectedItem="{Binding SelectedAction, Mode=TwoWay}"
于 2013-05-14T08:03:56.610 回答
3

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

<DataTemplate>
   <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
于 2016-05-27T07:06:56.330 回答
2

MyViewModel 类的 SelectedItem 属性不使用 INotifyPropertyChanged 接口,方法是在 setter 更改其值时引发 PropertyChanged 事件:

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

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

于 2013-05-14T07:54:58.907 回答
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; }
}
}
于 2013-05-14T08:11:44.453 回答
0

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

于 2014-03-22T17:47:32.387 回答
0

不仅“Erno de Weerd”答案正确,您需要通知您选择的属性的属性更改,而且 WPF DataGrid 是 Microsoft 提供的与 MVVM 相关的最容易出错的控件。

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

SelectedItem="{绑定 SelectedAction,UpdateSourceTrigger=PropertyChanged }"

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

于 2016-02-24T15:41:01.373 回答