Saltar al contenido

WPF – MVVM – ComboBox SelectedItem

Solución:

La categoría que está configurando en esta línea:

NodeCategory = some_list_of_other_objects.Category;

y uno presente en su colección de Categorías (ItemsSource="{Binding Categories}") debería referirse al mismo objeto. Si no lo son, entonces SelectedItem no funcionará.

Solución 1 –

También puedes intentar usar SelectedValuePath como esto –

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

y en el código puedes hacer algo como esto:

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

y establecer el elemento seleccionado como este –

NodeCategory = some_list_of_other_objects.Category.Name;

y use el valor seleccionado como este –

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

o

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

Solución 2 –

Otra posible solución puede ser:

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

de esta manera tu NodeCategory propiedad tendrá la referencia de un objeto en Categories colección y SelectedItem trabajará.

Su XAML necesita un par de modificaciones, pero creo que el problema real es con el código que ha publicado, que no creo que cuente la historia completa. Para empezar, tu combobox ItemSource está vinculado a una propiedad llamada Categorías, pero no muestra cómo se codifica esta propiedad o cómo su NodeCategory La propiedad se sincroniza inicialmente con el elemento.

Intente usar el siguiente código y verá que el elemento seleccionado se mantiene sincronizado a medida que el usuario cambia el valor en el cuadro combinado.

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>

Código detrás

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

De mi pequeño ejemplo:

Nota: Esto es establecer solo una cadena (o una categoría de otra lista), pero los conceptos básicos deberían ser los mismos aquí:

Básicamente esto se hace:

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

Aquí está mi 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>

y en el ViewModel de la ventana

class ComboBoxSampleViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string info)
    {
        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;
    }
}

Con la ayuda de esta pequeña clase:

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

Y este artículo ViewModel

public class ComboBoxSampleItemViewModel : 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");
        }
    }
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *