WPF MVVM ComboBox SelectedItem 返回上一个项目

问题描述 投票:0回答:1

我有一个 MVVM 绑定的 ComboBox

<ComboBox x:Name="CBRootPathComboBox"
  ItemsSource="{Binding RootPathComboBoxItems, Mode=OneTime}" 
  DisplayMemberPath="DisplayName"
  SelectedItem="{Binding SelectedRootPathComboBoxItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <i:InvokeCommandAction 
          Command="{Binding RootPathComboBoxItemSelectionChangedCommand}"
          CommandParameter="{Binding ElementName=CBRootPathComboBox, Path=SelectedItem}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ComboBox>

Interaction
来自
Microsoft.Xaml.Behaviors.Wpf
nuget。

SelectionChanged
上,我期望看到
ICommand
以及列表中当前选定的项目。

在 ViewModel 中,我在代码中的某个位置设置了

SelectedItem

我使用 ViewModel 属性在 ViewModel 中将其从“Item2”设置为“Item1”。

调用链如下:

1. set the property to "Item1"
2. Raise INotifyPropertyChanged.PropertyChanged event
3. .Net internals calls property getter, it returns "Item1"
4. ICommand call contains "Item2" in parameter. Expected: "Item1"

ViewModel 属性:

private RootPathItem _selectedRootPathComboBoxItem;
public RootPathItem SelectedRootPathComboBoxItem
{
  get
  {
    Debug.WriteLine($"getting {_selectedRootPathComboBoxItem?.DisplayName ?? "null"}");
    return _selectedRootPathComboBoxItem;
  }
  set
  {
    Debug.WriteLine($"setting {value?.DisplayName ?? "null"}");
    if (_selectedRootPathComboBoxItem != value)
    {
      Debug.WriteLine($"overwriting {_selectedRootPathComboBoxItem?.DisplayName ?? "null"}");
      _selectedRootPathComboBoxItem = value;
      this.OnPropertyChanged();
    }
  }
}

XAML:https://github.com/DJDoena/FolderSize/blob/bc0f316a321a5a1a752c4dd12484e2d8684b3700/View/MainWindow.xaml

ViewModel:https://github.com/DJDoena/FolderSize/blob/bc0f316a321a5a1a752c4dd12484e2d8684b3700/ViewModel/MainViewModel.cs

c# wpf mvvm combobox
1个回答
0
投票

几种解决方案。

  1. 无需使用事件。在虚拟机中实现所需的逻辑。对于您的代码来说,最简单的形式将是这样的:
private RootPathItem _selectedRootPathComboBoxItem;
public RootPathItem SelectedRootPathComboBoxItem
{
  get
  {
    Debug.WriteLine($"getting {_selectedRootPathComboBoxItem?.DisplayName ?? "null"}");
    return _selectedRootPathComboBoxItem;
  }
  set
  {
    Debug.WriteLine($"setting {value?.DisplayName ?? "null"}");
    if (_selectedRootPathComboBoxItem != value)
    {
      Debug.WriteLine($"overwriting {_selectedRootPathComboBoxItem?.DisplayName ?? "null"}");
      _selectedRootPathComboBoxItem = value;
      this.OnPropertyChanged();

      RootPathComboBoxItemSelectionChangedExecute(value);
    }
  }
}
  1. 从事件参数中检索新选定的元素:
<ComboBox x:Name="CBRootPathComboBox"
  ItemsSource="{Binding RootPathComboBoxItems, Mode=OneTime}" 
  DisplayMemberPath="DisplayName"
  SelectedItem="{Binding SelectedRootPathComboBoxItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <i:InvokeCommandAction 
          Command="{Binding RootPathComboBoxItemSelectionChangedCommand}"
          EventArgsParameterPath="AddedItems[0]" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ComboBox>
  1. 您可以使用 BeginInvoke 从事件异步调用命令,但为此您必须使用
    i:Interaction.Behaviors
    而不是
    i:Interaction.Triggers
    。代码中稍微复杂一些的是
    InvokeCommandAction
    Behavior
© www.soinside.com 2019 - 2024. All rights reserved.