WPF - MVVM - ComboBox SelectedItem

я имеюViewModel(реализованныйINotifyPropertyChanged) в фоновом режиме и классCategory который имеет только одно свойство типаstring, Мой ComboBox SelectedItem привязан к экземпляру категории. Когда я изменяю значение экземпляра, 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}"/>

Имущество:

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

и что я пытаюсь это: когда я устанавливаю

NodeCategory = some_list_of_other_objects.Category;

чтобы этот элемент был выбран вCombobox с соответствующимиDisplayMemberPath

 Andy16 июн. 2012 г., 11:41
Попробуйте добавить триггер источника обновлений в ваши привязки. UpdateSourceTrigger = PropertyChanged
 Bip16 июн. 2012 г., 11:37
Конечно, это добавлено :)
 Andy16 июн. 2012 г., 11:39
Работает ли привязка свойства SelectedItem вместо выбранного значения?
 Mare Infinitus16 июн. 2012 г., 11:35
Можете ли вы опубликовать код пожалуйста, особенно XAML
 Bip16 июн. 2012 г., 11:40
Нет, это то же самое.

Ответы на вопрос(3)

Ваш XAML нуждается в нескольких модификациях, но я думаю, что реальная проблема заключается в опубликованном вами коде, который, я думаю, не рассказывает полную историю. Для начала ваш комбобоксItemSource привязан к свойству под названием Категории, но вы не показываете, как это свойство закодировано или как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>

Code-behind

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;
}
 27 янв. 2017 г., 17:41
Этот ответ позволил мне получить +1. Для примера от начала до конца я написал об этом здесь:technical-recipes.com/2017/…
 Bip16 июн. 2012 г., 12:33
на данном этапе проекта невозможно добавить логику в пользовательский интерфейс, извините. Но TNX для ответа. проголосовал :)

Из моего маленького примера:

Примечание: это установка только строки (или категории из другого списка), но основы должны быть такими же:

В основном это сделано:

private void button1_Click(object sender, RoutedEventArgs e)
{
    (this.DataContext as ComboBoxSampleViewModel).SelectCategory("Categorie 4");
}

Вот мой XAML:

<Grid>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="76,59,0,0"   
              Name="comboBox1" VerticalAlignment="Top" Width="120" 
              ItemsSource="{Binding List.Categories}" 
              DisplayMemberPath="Name" 
              SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
    <Button Content="Button" Height="27" HorizontalAlignment="Left" 
            Margin="76,110,0,0" Name="button1" VerticalAlignment="Top" 
            Width="120" Click="button1_Click" />
</Grid>

и в ViewModel окна

class ComboBoxSampleViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string inf,o)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public CategoryList List { get; set; }

    public ComboBoxSampleViewModel()
    {
        this.List = new CategoryList();
        NodeCategory = List.Selected;
    }

    private ComboBoxSampleItemViewModel nodeCategory;
    public ComboBoxSampleItemViewModel NodeCategory
    {
        get
        {
            return nodeCategory;
        }
        set
        {
            nodeCategory = value;
            NotifyPropertyChanged("NodeCategory");
        }
    }

    internal void SelectCategory(string p)
    {
        this.List.SelectByName(p);
        this.NodeCategory = this.List.Selected;
    }
}

С помощью этого маленького класса:

public class CategoryList
{
    public ObservableCollection<ComboBoxSampleItemViewModel> Categories { get; set; }
    public ComboBoxSampleItemViewModel Selected { get; set; }
    public CategoryList()
    {
        Categories = new ObservableCollection<ComboBoxSampleItemViewModel>();

        var cat1 = new ComboBoxSampleItemViewModel() { Name = "Categorie 1" };
        var cat2 = new ComboBoxSampleItemViewModel() { Name = "Categorie 2" };
        var cat3 = new ComboBoxSampleItemViewModel() { Name = "Categorie 3" };
        var cat4 = new ComboBoxSampleItemViewModel() { Name = "Categorie 4" };

        Categories.Add(cat1);
        Categories.Add(cat2);
        Categories.Add(cat3);
        Categories.Add(cat4);

        this.Selected = cat3;
    }

    internal void SelectByName(string p)
    {
        this.Selected = this.Categories.Where(s => s.Name.Equals(p)).FirstOrDefault();
    }
}

И этот пункт ViewModel

public class ComboBoxSampleItemView,Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    private string name;

    public string Name 
    { 
        get
        {
            return name;
        }
        set
        {
            name = value;
            NotifyPropertyChanged("Name");
        }
    }
}
 Bip16 июн. 2012 г., 12:56
Акёши дал правильный ответ. но тнкс за пробой :)
 16 июн. 2012 г., 12:58
Хорошо, без проблем. решение очень похоже, насколько я вижу
Решение Вопроса

Категория, которую вы устанавливаете в этой строке -

NodeCategory = some_list_of_other_objects.Category;

и один подарок в вашей коллекции категорий (ItemsSource="{Binding Categories}") должен ссылаться на один и тот же объект. Если они не тогдаSelectedItem не будет работать.

Solution 1 -

Вы также можете попробовать использоватьSelectedValuePath как это -

<ComboBox x:Name="categoryComboBox" 
          ItemsSource="{Binding Categories}"
          DisplayMemberPath="Name" 
          SelectedValuePath="Name" 
          SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />

и в коде вы можете сделать что-то вроде этого -

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

и установить выбранный элемент, как это -

NodeCategory = some_list_of_other_objects.Category.Name;

и использовать выбранное значение, как это -

Category selectedCategory = 
   some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);

или же

Category selectedCategory = 
   Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);
Solution 2 -

Другое возможное решение может быть -

NodeCategory = 
  Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);

таким образом, ваше свойство NodeCategory будет иметь ссылку на объект в коллекции Categories иSelectedItem буду работать.

 16 июн. 2012 г., 12:32
Это именно то, что я хотел опубликовать сейчас.
 Bip16 июн. 2012 г., 12:32
позвольте мне объяснить немного больше. У меня есть список категорий. Категория 1, Категория 2 ... и т. Д. У меня есть сетка данных рядом с ней, и я щелкнул строку сетки данных. Хорошо. Теперь, когда я щелкнул по нему, все остальное заполняется его данными (у меня есть несколько текстовых полей), но в выпадающем списке выделенный элемент пуст
 15 авг. 2017 г., 16:19
Да DisplayMemberPath незаменим при использовании объектов
 16 июн. 2012 г., 12:44
@PredragPejic в случае, если ваши ComboBox и DataGrid - это два разных списка, для которых хорошим вариантом будет использование разных объектов, тогда использование SelectedValuePath.
 19 дек. 2017 г., 07:05
& quot; должен ссылаться на один и тот же объект & quot; спаси мой день! Спасибо за информацию.

Ваш ответ на вопрос