C# 如何从由对象填充的组合框中选择对象的实例

C# 如何从由对象填充的组合框中选择对象的实例,c#,.net,wpf,xaml,data-binding,C#,.net,Wpf,Xaml,Data Binding,这个问题可能很愚蠢,但我是WPF的新手,所以我很抱歉。 我在这里发现了很多类似的问题,但都没有帮助 我有一个表单,它获取一些带有位置属性的对象作为输入。 我希望在显示表单时在组合框中选择此位置属性。 我还希望使此属性在表单的生命周期中可以更改 我是这样做的: <ComboBox Name="CB_Location" ItemsSource="{Binding Locations}" SelectedItem="{Binding Select

这个问题可能很愚蠢,但我是WPF的新手,所以我很抱歉。 我在这里发现了很多类似的问题,但都没有帮助

我有一个表单,它获取一些带有
位置
属性的对象作为输入。 我希望在显示表单时在组合框中选择此
位置
属性。 我还希望使此属性在表单的生命周期中可以更改

我是这样做的:

<ComboBox Name="CB_Location" ItemsSource="{Binding Locations}" SelectedItem="{Binding SelectedLocation}" DisplayMemberPath="LocationName" SelectedValuePath="LocationID" SelectionChanged="CB_Location_SelectionChanged"/>
公共表单(object\u obj)
{
初始化组件();
lctrl=新位置控制器();
Locations=lctrl.GetAllLocations();
SelectedLocation=lctrl.GetLocationById(_obj.LocationID);
DataContext=this;
}
公共列表位置{get;set;}
公共场所选择场所;{get;set;}

组合框
正确填充了对象,但我无法正确设置
SelectedItem
属性。

未设置所选项目的原因是
SelectedLocation
是一个无法绑定的字段。有关绑定源的更多信息,请参阅

您可以绑定到任何公共语言运行库(CLR)对象的公共属性、子属性以及索引器。绑定引擎使用CLR反射来获取属性的值。或者,实现ICustomTypeDescriptor或具有注册的TypeDescriptionProvider的对象也可以使用绑定引擎

要使当前代码正常工作,只需将
SelectedLocation
设置为公共属性即可

public Location SelectedLocation { get; set; }
除此之外,如果您只想绑定所选项目,则设置
SelectedValuePath
是无用的

<ComboBox Name="CB_Location"
          ItemsSource="{Binding Locations}"
          SelectedItem="{Binding SelectedLocation}"
          DisplayMemberPath="LocationName"
          SelectionChanged="CB_Location_SelectionChanged"/>
然后,您可以使用值路径
LocationID
(不带
SelectedItem
)将其绑定到
SelectedValue


为什么在不使用SelectedValue的情况下设置SelectedValuePath?什么是SelectedLocation?如果它是当前DataContext中Location类型的属性,请确保其值是Location集合成员的Location对象。否则,将其转换为
int
类型的属性,绑定SelectedValue而不是SelectedItem,并将其设置为
SelectedLocation=\u obj.LocationID是,SelectedLocation是位置类型的属性。位置集合包含所有可能的位置,包括SelectedLocation。
公共位置SelectedLocation是一个字段,而不是属性。@Clemens修复了这个问题。非常感谢。但还是不行。谢谢那个家伙。我已经将SelectedLocation设置为公共财产。但是SelectedLocation仍然没有正确地应用于combobox。这很奇怪,但SelectedLocationID似乎起了作用。现在ComboBox显示值,SelectionChanged正在工作。我现在很感兴趣,哪种方法更正确:保持原样,还是继续尝试ObservableCollection之类的东西。@PavelPolushin这不应该与
ObservableCollection
相关。只有在运行时修改集合时才需要它。如果您在构造函数中创建了一个集合,但从未对其进行过修改,则不需要它,一个简单的列表就足够了(或只读集合)。考虑到
GetLocationById
返回与mm8在另一个答案中显示的
Locations
中存在的项的相同实例,这两种方法应该都可以正常工作。两者都是正确的,这取决于您的用例哪个更适合。重要的是不要在XAML中混合使用这两种方法(意外结果)。
public Location SelectedLocation { get; set; }
<ComboBox Name="CB_Location"
          ItemsSource="{Binding Locations}"
          SelectedItem="{Binding SelectedLocation}"
          DisplayMemberPath="LocationName"
          SelectionChanged="CB_Location_SelectionChanged"/>
public int SelectedLocationID { get; set; }
<ComboBox Name="CB_Location"
          ItemsSource="{Binding Locations}"
          DisplayMemberPath="LocationName"
          SelectedValuePath="LocationID"
          SelectedValue="{Binding SelectedLocationID}"
          SelectionChanged="CB_Location_SelectionChanged"/>
public class YourViewModel : INotifyPropertyChanged
{
   private Location _selectedLocation;
   public Location SelectedLocation
   {
      get => _selectedLocation;
      set
      {
         if (_selectedLocation == value)
            return;
   
         _selectedLocation = value;
         OnPropertyChanged();
      }
   }

   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }

   // ...other code.
}