WPF - MVVM - ComboBox SelectedItem

Bip*_*Bip 17 .net c# data-binding wpf mvvm

我已经ViewModel(实现INotifyPropertyChanged)在后台和类Category中只有一个属性类型string.我的ComboBox SelectedItem绑定到Category的实例.当我更改实例的值时,SelectedItem没有被更新,并且Combobox没有被更改.

编辑:代码

组合框:

<ComboBox x:Name="categoryComboBox" Grid.Column="1"  Grid.Row="3" Grid.ColumnSpan="2" 
          Margin="10" ItemsSource="{Binding Categories}"
          DisplayMemberPath="Name" SelectedValue="{Binding NodeCategory, Mode=TwoWay}"/>
Run Code Online (Sandbox Code Playgroud)

属性:

private Category _NodeCategory;
public Category NodeCategory
{
    get
    {
        return _NodeCategory;
    }
    set
    {
        _NodeCategory = value;
        OnPropertyChanged("NodeCategory");
    }
}

[Serializable]
public class Category : INotifyPropertyChanged
{
    private string _Name;
    [XmlAttribute("Name")]
    public string Name
    {
        get
        {
            return _Name;
        }
        set
        {
            _Name = value;
            OnPropertyChanged("Name");
        }
    }

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    [field:NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试的是:当我设置

NodeCategory = some_list_of_other_objects.Category;
Run Code Online (Sandbox Code Playgroud)

选择Combobox适当的项目DisplayMemberPath

akj*_*shi 20

您在此行中设置的类别 -

NodeCategory = some_list_of_other_objects.Category;
Run Code Online (Sandbox Code Playgroud)

您的Categories集合(ItemsSource="{Binding Categories}")中的一个应该引用同一个对象.如果他们不是那么SelectedItem将无法工作.

解决方案1 ​​ -

你也可以尝试这样使用SelectedValuePath-

<ComboBox x:Name="categoryComboBox" 
          ItemsSource="{Binding Categories}"
          DisplayMemberPath="Name" 
          SelectedValuePath="Name" 
          SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
Run Code Online (Sandbox Code Playgroud)

在代码中你可以做这样的事情 -

private string _NodeCategory;
public string NodeCategory
{
    get
    {
        return _NodeCategory;
    }
    set
    {
        _NodeCategory = value;
        OnPropertyChanged("NodeCategory");
    }
}
Run Code Online (Sandbox Code Playgroud)

并设置这样的选定项目 -

NodeCategory = some_list_of_other_objects.Category.Name;
Run Code Online (Sandbox Code Playgroud)

并使用这样的选定值 -

Category selectedCategory = 
   some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);
Run Code Online (Sandbox Code Playgroud)

要么

Category selectedCategory = 
   Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);
Run Code Online (Sandbox Code Playgroud)

解决方案2 -

另一个可能的解决方案是 -

NodeCategory = 
  Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);
Run Code Online (Sandbox Code Playgroud)

这样,您的NodeCategory属性将具有Categories集合中对象的引用,NodeCategory并将起作用.


Ben*_*ale 5

您的XAML需要进行一些修改,但是我认为真正的问题在于您发布的代码,而我认为这并不能说明全部内容。首先,您的组合框ItemSource绑定到一个名为Categories的属性,但没有显示此属性的编码方式或该NodeCategory属性最初与该项目的同步方式。

尝试使用以下代码,您将看到随着用户更改组合框中的值,所选项目保持同步。

XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <ComboBox x:Name="categoryComboBox"
              Grid.Column="1"
              Grid.Row="3"
              Grid.ColumnSpan="2"
              Margin="10"
              ItemsSource="{Binding Categories}"
              DisplayMemberPath="Name"
              SelectedItem="{Binding NodeCategory}" />
    <Label Content="{Binding NodeCategory.Name}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

代码隐藏

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Category> _categories = new ObservableCollection<Category>
    {
        new Category { Name = "Squares"},
        new Category { Name = "Triangles"},
        new Category { Name = "Circles"},
    };

    public MainWindow()
    {
        InitializeComponent();
        NodeCategory = _categories.First();
        this.DataContext = this;
    }

    public IEnumerable<Category> Categories
    {
        get { return _categories; }
    }

    private Category _NodeCategory;
    public Category NodeCategory
    {
        get
        {
            return _NodeCategory;
        }
        set
        {
            _NodeCategory = value;
            OnPropertyChanged("NodeCategory");
        }
    }

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

[Serializable]
public class Category : INotifyPropertyChanged
{
    private string _Name;
    [XmlAttribute("Name")]
    public string Name
    {
        get
        {
            return _Name;
        }
        set
        {
            _Name = value;
            OnPropertyChanged("Name");
        }
    }

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)