将项目添加到数据网格中的组合框 [英] adding items to a combobox in the datagrid

查看:167
本文介绍了将项目添加到数据网格中的组合框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个简单的数据网格由组合框和文本框组成。名为cost的最后一个字段是一个文本框,所选组合框的组合结果。这是xaml:

 < DataGrid AutoGenerateColumns =Falsex:Name =myGridItemsSource ={Binding Path =路由,UpdateSourceTrigger = PropertyChanged}> 
< DataGrid.Columns>
< DataGridTextColumn Header =Sequenza N°/>
< DataGridComboBoxColumn Width =100x:Name =Product
SelectedValueBinding ={Binding Product,Mode = TwoWay,UpdateSourceTrigger = PropertyChanged}Header =Product
DisplayMemberPath = {Binding Product}>
< / DataGridComboBoxColumn>
< DataGridComboBoxColumn Width =100x: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>

后面的代码是一个名为Routing的类,它定义一个值列表,并使用propertychanged来更改成本文本框值。

 命名空间weblego 
{
public partial class Prepare:Window
{

public List< Routing>路线{get;组; }
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 =路由;
}
}
public class Routing:INotifyPropertyChanged
{
private string product;
public string Product
{
get {return product;
set
{
if(product!= value)
{
product = value;
OnPropertyChanged(value);
}
}
}

私有字符串质量;
public string质量
{
get {return quality;
set
{
if(quality!= value)
{
quality = value;
UpdateCost();
OnPropertyChanged(value);
}
}
}


私人双重成本;
public double成本
{
get {return cost; }
set
{
if(cost!= value)
{
cost = value;
OnPropertyChanged(Cost);
}
}
}

public void UpdateCost()
{
double qualityMultiple = 1;
开关(质量)
{
casehigh:
qualityMultiple = 1.5;
break;
casemedium:
qualityMultiple = 1;
break;
caselow:
qualityMultiple = 0.5;
break;
}

开关(产品)
{
casestazione1:
成本= 10 * qualityMultiple;
break;
casestazione2:
成本= 15 * qualityMultiple;
break;
casestazione3:
成本= 12.5 * qualityMultiple;
break;
}

}

//创建OnPropertyChanged方法来引发事件
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!= null)
{
handler(this,new PropertyChangedEventArgs(name));
}
}
}
}

工作正常,但我做了计划错误。称为成本的xaml中的最后一个字段应该是一个组合框,而不是一个文本框,并且必须填充来自数据库的值。所以XAML应该成为:

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

后面的代码应该让我以某种方式更改Cost元素上的itemsource。 >

 私人列表< string>成本; 
public List< string>成本
{
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);
}

}

但是当我这样做得到一个System.NullReferenceException'说成本是空的。

解决方案

好的,我可以根据行中其他字段中选定的值来更改最后一个组合框的项目来源吗?你将需要两件事来组合你的组合框。首先,您的组合框的成本列表或ItemsSource。



下面是一个工作示例:



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 =MainWindowHeight =350Width =525>
< DataGrid AutoGenerateColumns =Falsex:Name =myGridItemsSource ={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标题=质量>
< 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标题=质量>
< 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>

窗口代码:

 使用系统; 
使用System.Collections.ObjectModel;
使用System.ComponentModel;
使用System.Windows;


命名空间Sandpit
{
public partial class MainWindow:Window,INotifyPropertyChanged
{
public ObservableCollection< Routing>路线
public ObservableCollection< Routing>路线
{
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));
}
}
}
}

Route对象:

 使用System.Collections.ObjectModel; 
使用System.ComponentModel;

命名空间Sandpit
{
public class Routing:INotifyPropertyChanged
{
private ObservableCollection< string>可用产品;
public ObservableCollection< string>可用产品
{
get {return availableProducts;
set
{
if(availableProducts!= value)
{
availableProducts = value;
OnPropertyChanged(AvailableProducts);
}
}
}
私有字符串产品;
public string Product
{
get {return product;
set
{
if(product!= value)
{
product = value;
UpdateAvailableCosts();
OnPropertyChanged(Product);
}
}
}
private ObservableCollection< string>可用质量
public ObservableCollection< string> AvailableQuality
{
get {return availableQuality;
set
{
if(availableQuality!= value)
{
availableQuality = value;
OnPropertyChanged(AvailableQuality);
}
}
}
私有字符串质量;
public string质量
{
get {return quality;
set
{
if(quality!= value)
{
quality = value;
UpdateAvailableCosts();
OnPropertyChanged(质量);
}
}
}

//用户可以使用的费用。当质量等更改时,这些更新
private ObservableCollection< string>可用的
public ObservableCollection< string> AvailableCosts
{
get {return availableCosts;
set
{
if(availableCosts!= value)
{
availableCosts = value;
OnPropertyChanged(AvailableCosts);
}
}
}

私人字符串成本;
public string Cost
{
get {return cost; }
set
{
if(cost!= value)
{
cost = value;
OnPropertyChanged(Cost);
}
}
}

public void UpdateAvailableCosts()
{
//删除旧的可用选项
AvailableCosts。明确();
//只需填写由质量和成本组成的两个项目,演示
AvailableCosts.Add(质量+产品);
AvailableCosts.Add(产品+质量);
//确保我们目前的成本在列表中,只需清除
Cost =;
}

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

//创建OnPropertyChanged方法来引发事件
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!= null)
{
handler(this,new PropertyChangedEventArgs(name));
}
}
}
}

生产:





并更改内容:





完美运作。


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?

解决方案

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.

这篇关于将项目添加到数据网格中的组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆