【问题标题】:WPF Combobox loses binding to SelectedItem when changing the view model更改视图模型时,WPF Combobox 失去与 SelectedItem 的绑定
【发布时间】:2017-01-09 16:03:43
【问题描述】:

我有一个组合框可以更改对象类型。选择新类型时,我会破坏旧视图模型并绑定到新视图模型。当我这样做时,组合框不再更新选定的项目属性。

组合框声明如下所示。请注意,此组合框位于 ListView 的 ItemTemplate 中。

<ListView ItemSource="{Binding MyViewModels}">
    <ListView.ItemTemplate>
        <DataTemplate DataType="viewModels:MyTypeViewModel">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Type:" Width="170"/>
                <ComboBox  SelectedItem="{Binding Type}"
                                          ItemsSource="{Binding Source={StaticResource MyEnumTypes}}"
                                          Width="150"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

失去绑定的属性如下所示。请注意,我没有调用 OnPropertyChanged,因为该类使用 Fody.PropertyChanged 包,并且该类标有 [ImplementsPropertyChanged]。

    public MyType Type { get; set; }
    {
        get { return _type; }
        set
        {
            if (_type == value) return;

            _type = value;

            OnMyTypeChanged?.Invoke(this, new MyTypeChangedEventArgs(_type));
        }
    }

类型改变的回调如下所示。

    private void OnMyTypeChanged(object sender, MyTypeChangedEventArgs args)
    {
        var index = MyViewModels.IndexOf(sender as MyViewModel);

        var selected = SelectedMyViewModel == MyViewModels[index]; 

        var tmp = CreateReplacementViewModelByType(args.Type, MyViewModels[index].Model.Address);

        if (selected)
            SelectedMyViewModel = tmp;

        MyViewModels[index] = tmp;

        MyViewModels[index].OnMyTypeChanged += OnMyTypeChanged;
    }

第一次更改对象的类型时,视图模型会正确更新。之后更改组合框的选定项甚至不会调用属性的 Set 函数。不知何故,组合框保持其旧的绑定。

我的视图的 DataContext 在程序开始时在后面的代码中分配一次。上下文本身是一个单例管理器类,它执行视图模型的实际交换。初始化看起来像这样。否则不会更新。

    public MainWindow()
    {
        InitializeComponent();

        //Set the global DataContext
        DataContext = MyTypeManager.Instance;
    }

MyViewModels 属性在管理器类中声明为 observablecollection,如下所示:

    public ObservableCollection<MyViewModel> MyViewModels { get; } = new ObservableCollection<MyViewModel>();

我在 Visual Studio 2015 中创建了一个测试应用程序,这里是存储库的链接。 https://github.com/df424/WFPComboBoxTest

【问题讨论】:

  • 如何设置视图的DataContext?请向我们提供minimal reproducible example
  • 我已经修改了帖子以包含有关 DataContext 设置位置的信息。
  • 请发布 MyViewModels 属性
  • 我用这部分更新了帖子。
  • @ghost 更改内容后不调用 CollectionChanged 事件。这可能会导致 UI 无法重新绑定到新实体。

标签: wpf


【解决方案1】:

要绑定到 Enum 数据源,请先添加一个 ResourceDictionary,其中包含以下内容

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:utility="clr-namespace:MyApp;assembly=MyApp">
  <ObjectDataProvider x:Key="MyEnumTypesSource" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
    <ObjectDataProvider.MethodParameters>
      <x:Type TypeName="MyApp:MyEnumTypes" />
    </ObjectDataProvider.MethodParameters>
  </ObjectDataProvider>
</ResourceDictionary>

然后将资源字典添加到你的窗口或应用中

<Window.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="/Resources/EnumDataSources.xaml" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Window.Resources>

最后添加你的 ComboBox 绑定如下

<ComboBox Height="24" Width="100" ItemsSource="{Binding Source={StaticResource MyEnumTypesSource}}"
    SelectedValue="{Binding MyViewModel.MyCurrentEnumValue}" />

ViewModel 属性基本上应该如下所示。

public MyApp.MyEnumTypes MyCurrentEnumValue
{
    get { return m_MyCurrentEnumValue; }
    set
    {
        m_MyCurrentEnumValue = value;
        OnPropertyChanged("MyCurrentEnumValue");
    }
}

【讨论】:

  • 您好,谢谢您的回复。枚举按预期显示为组合框中的选项。反映财产的当前状态也没有问题。当我切换视图模型时,问题就来了。完成此操作后,在组合框中选择新值不再调用 Type 属性的 set 函数。有趣的是,在我没有包含的类中还有其他属性仍然可以正确更新。
猜你喜欢
  • 2011-11-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-28
  • 2010-10-24
  • 1970-01-01
  • 2017-11-09
  • 2016-03-25
  • 1970-01-01
相关资源
最近更新 更多