adding items to a combobox in the datagrid

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-06 15:32:37

问题


ive got a simple datagrid made out of comboboxes and textboxes. the last field named "cost" is a textbox,result of the combination of the comboboxes selected. Here's the xaml:

<DataGrid AutoGenerateColumns="False" x:Name="myGrid"  ItemsSource="{Binding Path=Routes,UpdateSourceTrigger=PropertyChanged}" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Sequenza N°"/>
            <DataGridComboBoxColumn Width="100" x:Name="Product" 
        SelectedValueBinding="{Binding Product, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Header="Product" 
        DisplayMemberPath="{Binding Product}"  >
            </DataGridComboBoxColumn>  
            <DataGridComboBoxColumn Width="100" x:Name="Quality" 
        SelectedValueBinding="{Binding Quality, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Header="Cestello" 
        DisplayMemberPath="{Binding Quality}"  >
            </DataGridComboBoxColumn>
            <DataGridTextColumn Binding="{Binding Cost, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Header="Cost"/>
        </DataGrid.Columns>
    </DataGrid>

And the code behind is a class called Routing which defines a list of values and used propertychanged to change the Cost textbox value.

namespace weblego
{
public partial class Prepare : Window
{

    public List<Routing> Routes { get; set; }
    public Prepare()
    {
        InitializeComponent();
        Routes = new List<Routing>()
            {
            new Routing() { Product = "triangolo"}
            };
        string[] stazioni = { "stazione1", "stazione2", "stazione3" };
        string[] qualita = { "low", "medium", "high" };
        Product.ItemsSource = stazioni;
        Quality.ItemsSource = qualita;
        myGrid.ItemsSource = Routes;
    }
}
public class Routing : INotifyPropertyChanged
{
    private string product;
    public string Product
    {
        get { return product; }
        set
        {
            if (product != value)
            {
                product = value;
                OnPropertyChanged(value);
            }
        }
    }

    private string quality;
    public string Quality
    {
        get { return quality; }
        set
        {
            if (quality != value)
            {
                quality = value;
                UpdateCost();
                OnPropertyChanged(value);
            }
        }
    }


    private double cost;
    public double Cost
    {
        get { return cost; }
        set
        {
            if (cost != value)
            {
                cost = value;
                OnPropertyChanged("Cost");
            }
        }
    }

    public void UpdateCost()
    {
        double qualityMultiple = 1;
        switch (Quality)
        {
            case "high":
                qualityMultiple = 1.5;
                break;
            case "medium":
                qualityMultiple = 1;
                break;
            case "low":
                qualityMultiple = 0.5;
                break;
        }

        switch (Product)
        {
            case "stazione1":
                Cost = 10 * qualityMultiple;
                break;
            case "stazione2":
                Cost = 15 * qualityMultiple;
                break;
            case "stazione3":
                Cost = 12.5 * qualityMultiple;
                break;
        }

    }

    // Create the OnPropertyChanged method to raise the event
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}
}

everything works fine,but i made a planning error. the last field in the xaml called "Cost" is supposed to be a combobox,not a textbox,and must be filled with values coming from a database. so the XAML should become:

<DataGridComboBoxColumn Width="100" x:Name="Cost" 
        SelectedValueBinding="{Binding Cost, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Header="Cost" 
        DisplayMemberPath="{Binding Cost}" />

And the code behind should let me change the itemsource on the Cost element in some way.

    private List<string> cost;
    public List<string> Cost
    {
        get { return cost; }
        set
        {
            if (cost != value)
            {
                cost = value;
                OnPropertyChanged("Cost");
            }
        }
    }
        public void UpdateCost()
    {
        if(Quality=="high" && Product == "stazione1")
        {
            Cost.Add("abc");
            Cost.Add("def");
        }

    }

But when i do this,i get a System.NullReferenceException' saying the Cost is null. How can i change the itemsource of the last combobox depending on the selected values in the other fields of the row?


回答1:


Okay, You're going to need two things for your combo box to work. First, the list of costs or ItemsSource for your combobox. The next is your actual selectedCost.

Here is a working example:

xaml:

<Window x:Name="window"
        x:Class="Sandpit.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Sandpit"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <DataGrid AutoGenerateColumns="False" x:Name="myGrid"  ItemsSource="{Binding Routes}" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Sequenza N°" />
            <DataGridTemplateColumn Header="Product">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Product}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding AvailableProducts}"
                                  SelectedValue="{Binding Product, UpdateSourceTrigger=PropertyChanged}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Quality">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Quality}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding AvailableQuality}"
                                  SelectedValue="{Binding Quality, UpdateSourceTrigger=PropertyChanged}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Quality">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Cost}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding AvailableCosts}"
                                  SelectedValue="{Binding Cost, UpdateSourceTrigger=PropertyChanged}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

Window code:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;


namespace Sandpit
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public ObservableCollection<Routing> routes;
        public ObservableCollection<Routing> Routes 
        {
            get
            {
                return routes;
            }

            set
            {
                if (value != routes)
                {
                    routes = value;
                    NotifyPropertyChanged("Routes");
                }
            }
        }
        public MainWindow()
        {
            Routes = new ObservableCollection<Routing>();
            Routes.Add(new Routing { Product = "A", Quality = "C" });
            Routes.Add(new Routing { Product = "B", Quality = "D" });
            InitializeComponent();
            DataContext = this;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

And the Route object:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Sandpit
{
    public class Routing : INotifyPropertyChanged
    {
        private ObservableCollection<string> availableProducts;
        public ObservableCollection<string> AvailableProducts
        {
            get { return availableProducts; }
            set
            {
                if (availableProducts != value)
                {
                    availableProducts = value;
                    OnPropertyChanged("AvailableProducts");
                }
            }
        }
        private string product;
        public string Product
        {
            get { return product; }
            set
            {
                if (product != value)
                {
                    product = value;
                    UpdateAvailableCosts();
                    OnPropertyChanged("Product");
                }
            }
        }
        private ObservableCollection<string> availableQuality;
        public ObservableCollection<string> AvailableQuality
        {
            get { return availableQuality; }
            set
            {
                if (availableQuality != value)
                {
                    availableQuality = value;
                    OnPropertyChanged("AvailableQuality");
                }
            }
        }
        private string quality;
        public string Quality
        {
            get { return quality; }
            set
            {
                if (quality != value)
                {
                    quality = value;
                    UpdateAvailableCosts();
                    OnPropertyChanged("Quality");
                }
            }
        }

        //costs that are available to the user. These get updated when quality etc is changed
        private ObservableCollection<string> availableCosts;
        public ObservableCollection<string> AvailableCosts
        {
            get { return availableCosts; }
            set
            {
                if (availableCosts != value)
                {
                    availableCosts = value;
                    OnPropertyChanged("AvailableCosts");
                }
            }
        }

        private string cost;
        public string Cost
        {
            get { return cost; }
            set
            {
                if (cost != value)
                {
                    cost = value;
                    OnPropertyChanged("Cost");
                }
            }
        }

        public void UpdateAvailableCosts()
        {
            //remove the old available options
            AvailableCosts.Clear();
            //populate it with just two items made up of the quality and cost for demo
            AvailableCosts.Add(Quality + Product);
            AvailableCosts.Add(Product + Quality);
            //make sure our current cost is in the list by just clearing it
            Cost = "";
        }

        public Routing()
        {
            AvailableProducts = new ObservableCollection<string> { "A", "B" };
            AvailableQuality = new ObservableCollection<string> { "C", "D" };
            AvailableCosts = new ObservableCollection<string>();
        }

        // Create the OnPropertyChanged method to raise the event
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

Produces:

and changing things:

Works perfectly.



来源:https://stackoverflow.com/questions/36603993/adding-items-to-a-combobox-in-the-datagrid

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!