Search code examples
c#wpfdata-bindingcomboboxxelement

How to binding XDocument element to combobox in MVVM?


I have a XDocument read from xml file:

    public ObservableCollection<Product> GetProducts()
    {
        ObservableCollection<Product> _products = new ObservableCollection<Product>();
        XDocument doc = XDocument.Load(@".\Config\MCU.xml");
        foreach (XElement productRow in doc.Root.Elements("MCU"))
        {
            var m = new Product(productRow.Element("MCUName").Value, Convert.ToUInt32(productRow.Element("MCUNumber").Value), Convert.ToUInt32(productRow.Element("FlashAddress").Value),
                Convert.ToUInt32(productRow.Element("PageCount").Value), Convert.ToUInt32(productRow.Element("PageSize").Value), productRow.Element("BinFile").Value,
                Convert.ToUInt32(productRow.Element("RAMCodeAdd").Value), Convert.ToUInt32(productRow.Element("MainCR").Value), Convert.ToUInt32(productRow.Element("CRTrimmingAdd").Value),
                Convert.ToUInt32(productRow.Element("CRTrimmingLength").Value), Convert.ToUInt32(productRow.Element("UIDAdd").Value), Convert.ToByte(productRow.Element("UIDLength").Value),
                productRow.Element("UID").Value, productRow.Element("UserArea").Value);

            _products.Add(m);
        }
        return _products;
    }

Now I want to binding XElement MCUName to combobox:

<ComboBox x:Name="cb_MCUType" SelectedItem="{Binding MCUName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

ItemsSouce in the code behind:

    public MainWindow()
    {
        InitializeComponent();
        cb_MCUType.ItemsSource = App.ProductDb.GetProducts();
    }

But this doesn't work, the combobox populate the Product, how should I fix this? Thanks!

Update:

Thanks for the replies. As you suggested, now I would like to write this in MVVM, so I change my original code:

XAML:

<ComboBox x:Name="cb_MCUType" ItemsSource="{Binding ProductsList}" SelectedValue="{Binding SelectedProduct}" DisplayMemberPath="MCUName" />

ViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    private ProductDB pd = new ProductDB();

    public MainViewModel()
    {
       DefaultValue_Load();
    }

    public ObservableCollection<Product> ProductsList { get; set; }

    private Product _selectedProduct; 
    public Product SelectedProduct 
    { 
       get { return _selectedProduct; } 
       set
       {
          _selectedProduct = value;
          NotifyPropertyChanged("SelectedProduct"); 
       }
    }

    public void DefaultValue_Load()
    {

        ProductsList = new ObservableCollectioin<Product>(pd.GetProducts());
    }
}

Solution

  • When you create the Products in GetProducts() you provide MCUName as the first parameter in the constructor. For the following sample, I'll assume, that there is a property McuName on every product:

    public MainWindow()
    {
        InitializeComponent();
        cb_MCUType.ItemsSource = App.ProductDb.GetProducts().Select(p => p.McuName);
    }
    

    It is worth to mention, that this is not a clean MVVM implementation. You should consider to redesign your application to follow the MVVM patter.