2016-04-13 2 views
0

У меня есть простой набор данных, сделанный из comboboxes и текстовых полей. последнее поле с именем «стоимость» представляет собой текстовое поле, результат комбинации выбранных combobox. Вот XAML:добавление элементов в поле со списком в datagrid

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

И коды за классом называется маршрутизация, которая определяет список значений и использованное PropertyChanged изменить значение стоимости текстового поля.

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

все работает нормально, но я сделал ошибку планирования. последнее поле в xaml, называемое «Стоимость», должно быть полем со списком, а не текстовым полем, и должно заполняться значениями, поступающими из базы данных. поэтому XAML должно стать:

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

И код позади должен позволить мне изменить ItemSource на элементе затрат в некотором роде.

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

    } 

Но когда я это делаю, я получаю исключение System.NullReferenceException, говорящее, что стоимость равна нулю. Как я могу изменить источник элементов последнего списка со списком в зависимости от выбранных значений в других полях строки?

ответ

1

Хорошо, вам понадобится две вещи для вашей комбинированной коробки. Во-первых, список затрат или ItemsSource для вашего combobox. Следующий ваш фактический selectedCost.

Вот рабочий пример:

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> 

код окна:

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

И объект Route:

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

Производит:

enter image description here

и изменение вещей:

enter image description here

работает отлично.

+0

Theres ошибку в XAML, SelectedItem не определено, может быть, вы имели в виду SelectedValueBinding? также ошибка исключения в процедуру UpdateCost, она говорит AvailableCosts.Clear(); is null – frankiehf

+1

Извините, да, это SelectedItemBinding с сеткой со списками. Вы захотите создать AvailableCosts в своем конструкторе. – Joe

+0

что-то вроде этого? public void UpdateCost() { // удалить старые доступные опции ObservableCollection AvailableCosts = new ObservableCollection (); Доступные цены.Очистить(); // добавьте новые if (Quality == "high" && Operation == "stazione1") { AvailableCosts.Add ("abc"); AvailableCosts.Add ("def"); } // убедитесь, что наша текущая стоимость находится в списке, просто сделав ее первой. Cost = AvailableCosts [0]; } – frankiehf

Смежные вопросы