Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# wpf datagrid根据选定的值生成行 型号: 枚举: 温德罗斯: 视图:_C#_Wpf_Mvvm_Binding_Datagrid - Fatal编程技术网

C# wpf datagrid根据选定的值生成行 型号: 枚举: 温德罗斯: 视图:

C# wpf datagrid根据选定的值生成行 型号: 枚举: 温德罗斯: 视图:,c#,wpf,mvvm,binding,datagrid,C#,Wpf,Mvvm,Binding,Datagrid,现在让我们看看这个视图xaml,它被用作创建新windrose的模式窗口: <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto

现在让我们看看这个视图xaml,它被用作创建新windrose的模式窗口:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>                

  <Label Grid.Row="0" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Name" />
  <TextBox Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />

  <Label Grid.Row="1" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Number of directions" />
  <ComboBox Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" SelectedItem="{Binding Path=NumberOfDirections, UpdateSourceTrigger=PropertyChanged}">
    <ComboBoxItem Content="4" />
    <ComboBoxItem Content="8" />
    <ComboBoxItem Content="12" />
    <ComboBoxItem Content="16" />
    <ComboBoxItem Content="36" />   
  </ComboBox>

  <Label Grid.Row="2" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Stability Level" />
  <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Vertical">
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Unstable}}" Content="A - Unstable" />
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Neutral}}" Content="B - Neutral" />
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Stable}}" Content="C - Stable" />
  </StackPanel>

  <Grid Grid.Row="3" Grid.ColumnSpan="2">                    
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <RadioButton Grid.Row="0" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class1}}" Content="1 - 0 to 2 meters per second"  />
    <TextBox Grid.Row="0" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

    <RadioButton Grid.Row="1" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class2}}" Content="2 - 2 to 4 meters per second" />
    <TextBox Grid.Row="1" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

    <RadioButton Grid.Row="2" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class3}}" Content="3 - over 4 meters per second" />
    <TextBox Grid.Row="2" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
  </Grid>

  <DataGrid Grid.Row="4" Margin="5" ItemsSource="{Binding Percentage}"  AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTextColumn Header="Wind direction" Width="SizeToHeader">
      </DataGridTextColumn>

      <DataGridTemplateColumn Header="Percentage" Width="SizeToHeader">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBox Text="{Binding ???}"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
    </DataGrid.Columns>
  </DataGrid>  

 </Grid>
因此,对于每个“稳定性级别”“windspeed类”对,windrose实例保留一个包含37个值和一个额外浮点值的数组

我不知道如何做两件事:

A. 我不知道如何创建这个表DataGrid。我希望能够更改根据所选NumberOfDirections动态生成的行数。 选定的NumberOfDirections还确定了步进360度除以两个后续行之间的NumberOfDirections

B 在x:Name=WSClass的网格中,我希望能够将_average数组的项绑定到文本框,以便每个文本框对应于表示风速级别的某个RadioButton 具有值_平均[选定的稳定性][相应单选按钮的风速]

2013年11月22日编辑: 我问了一个关于如何实现这一目标的简单机制的问题。 用户已经回答了。由于我不能要求他在这个问题的背景下重写他对我问题的解决方案,我决定正确回答这个问题的唯一方法就是回答我自己的问题

警告:长柱

模型类: 查看模型类: 风向: 当我创建一个数据类型类来保存我需要在datagrid行中显示的所有信息时

所以

它实现INotifyPropertyChanged接口 为要在datagrid中显示的每个列实现一个属性 AddModifyWindroseDialogViewModel: 视图中的组合框有一个ObservableCollection,StabilityLevel WindspeedClass的每个组合都有一个ObservableCollection。因为用户必须能够一次编辑所有这些信息,所以我们为其创建了一个锯齿状数组

基本上,我们的想法是,基于2个属性的值,这两个属性决定了稳定性水平和风速等级,我们通过第三个属性返回适当的ObservableCollection。如果用户更改整个windrose的方向数,我们将调用私有方法UpdateFilteredItems。拥有ObservableCollection实际上允许我们将其绑定到DataGrid的ItemsSource,然后自己定义DataGrid的列,并将WindroseWindDirection的各个属性绑定到这些列

// just for reference: MVVM Light base view model class is used
public class AddModifyWindroseDialogViewModel : ViewModelBase
{
    #region Fields

    // holds the actual model class
    private Windrose _wr;
    // holds an ObservableCollection for each combination of StabilityLevel & WindspeedClass
    private ObservableCollection<WindroseWindDirection>[][] _dataGrid;
    // for Combobox
    private ObservableCollection<int> _numberOfDirectionValues = new ObservableCollection<int>(Constants.WindroseAllowedNumberOfDirections);    

    #endregion

        #region Construction

        public AddModifyWindroseDialogViewModel(Windrose windrose)
        {            
            _wr = windrose;            

            // create array[][] of observable collections, one for each stability <-> windspeed pair
            _dataGrid = new ObservableCollection<WindroseWindDirection>[Enum.GetNames(typeof(StabilityLevel)).Length][];
            int step = 360 / NumberOfDirections;
            foreach (StabilityLevel stability ... )
            {
                _dataGrid[(int) stability] = new ObservableCollection<WindroseWindDirection>[Enum.GetNames(typeof(WindspeedClass)).Length];
                foreach (WindspeedClass windspeed ... )
                {
                    _dataGrid[(int)stability][(int)windspeed] = new ObservableCollection<WindroseWindDirection>();
                    // Add 'No wind' special first row
                    _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection("No wind", _wr[stability, windspeed, 0]));
                    // Add the rest
                    for (int i = 0; i < NumberOfDirections; i++)
                    {
                        _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection(String.Format("{0} degrees", i * step), _wr[stability, windspeed, i + 1]));
                    }
                }
            }
        }

        #endregion

        #region Properties

        public String Name
        {
            get
            {
                return _wr.Name;
            }
            set
            {
                if (String.Equals(_wr.Name, value) == false)
                {
                    _wr.Name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        public int NumberOfDirections
        {
            get
            {
                return _wr.NumberOfDirections;
            }
            set
            {
                if (_wr.NumberOfDirections != value)
                {
                    _wr.NumberOfDirections = value;
                    RaisePropertyChanged("NumberOfDirections");
                    UpdateFilteredItems();
                }
            }
        }        
        public ObservableCollection<int> NumberOfDirectionsValues
        {
            get
            {
                return _numberOfDirectionValues;
            }
        }
        public StabilityLevel StabilityLevel
        {
            get
            {
                return _wr.StabilityLevel;
            }
            set
            {
                if (Enum.Equals(_wr.StabilityLevel, value) == false)
                {
                    _wr.StabilityLevel = value;
                    RaisePropertyChanged("StabilityLevel");
                    RaisePropertyChanged("FilteredItems");
                    RaisePropertyChanged("WindSpeedAverageClass1");
                    RaisePropertyChanged("WindSpeedAverageClass2");
                    RaisePropertyChanged("WindSpeedAverageClass3");                                        
                }
            }
        }
        public WindspeedClass Windspeed
        {
            get
            {
                return _wr.Windspeed;
            }
            set
            {
                if (Enum.Equals(_wr.Windspeed, value) == false)
                {
                    _wr.Windspeed = value;
                    RaisePropertyChanged("Windspeed");
                    RaisePropertyChanged("FilteredItems");
                }
            }
        }
        public ObservableCollection<WindroseWindDirection> FilteredItems
        {
            get
            {
                return _dataGrid[(int) StabilityLevel][(int) Windspeed];
            }
        }
        public float WindSpeedAverageClass1
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class1];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class1] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class1] = value;
                    RaisePropertyChanged("WindSpeedAverageClass1");
                }
            }
        }        
        public float WindSpeedAverageClass2
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class2];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class2] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class2] = value;
                    RaisePropertyChanged("WindSpeedAverageClass2");
                }
            }
        }
        public float WindSpeedAverageClass3
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class3];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class3] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class3] = value;
                    RaisePropertyChanged("WindSpeedAverageClass3");
                }
            }
        }        

        #endregion

        private void UpdateFilteredItems()
        {
            /**/
            int step = 360 / NumberOfDirections;
            foreach (StabilityLevel stability ... )
            {                
                foreach (WindspeedClass windspeed ... )
                {
                    // Clear the old values
                    _dataGrid[(int)stability][(int)windspeed].Clear();                    
                    // Add 'No wind' special value
                    _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection("No wind", _wr[stability, windspeed, 0]));
                    // Add degrees
                    for (int i = 0; i < NumberOfDirections; i++)
                    {
                        _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection(String.Format("{0} degrees", i * step), _wr[stability, windspeed, i + 1]));
                    }
                }
            }
            RaisePropertyChanged("FilteredItems");
        }                                            

}
视图:
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>                

  <Label Grid.Row="0" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Name" />
  <TextBox Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />

  <Label Grid.Row="1" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Number of directions" />
  <ComboBox Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" SelectedItem="{Binding Path=NumberOfDirections, UpdateSourceTrigger=PropertyChanged}">
    <ComboBoxItem Content="4" />
    <ComboBoxItem Content="8" />
    <ComboBoxItem Content="12" />
    <ComboBoxItem Content="16" />
    <ComboBoxItem Content="36" />   
  </ComboBox>

  <Label Grid.Row="2" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Stability Level" />
  <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Vertical">
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Unstable}}" Content="A - Unstable" />
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Neutral}}" Content="B - Neutral" />
    <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Stable}}" Content="C - Stable" />
  </StackPanel>

  <Grid Grid.Row="3" Grid.ColumnSpan="2">                    
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <RadioButton Grid.Row="0" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class1}}" Content="1 - 0 to 2 meters per second"  />
    <TextBox Grid.Row="0" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

    <RadioButton Grid.Row="1" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class2}}" Content="2 - 2 to 4 meters per second" />
    <TextBox Grid.Row="1" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

    <RadioButton Grid.Row="2" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class3}}" Content="3 - over 4 meters per second" />
    <TextBox Grid.Row="2" Grid.Column="1" Width="30" Text="{Binding Path=???, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
  </Grid>

  <DataGrid Grid.Row="4" Margin="5" ItemsSource="{Binding Percentage}"  AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTextColumn Header="Wind direction" Width="SizeToHeader">
      </DataGridTextColumn>

      <DataGridTemplateColumn Header="Percentage" Width="SizeToHeader">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBox Text="{Binding ???}"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
    </DataGrid.Columns>
  </DataGrid>  

 </Grid>
public enum StabilityLevel
{
    Unstable,
    Neutral,
    Stable
}

public enum WindspeedClass
{
    Class1,
    Class2,
    Class3
}

public class Windrose
{
  #region Fields
  // percentual value for given direction
  private short[][][] _percentage;        
  // average wind speed in wind speed class for given stability level        
  private float[][] _average;
  #endregion


  public Windrose()  {    ... initialization ...  }

  #region Properties

  public string Name { get; set; }
  public int NumberOfDirections { get; set; }
  public StabilityLevel StabilityLevel { get; set; }
  public WindspeedClass Windspeed { get; set; }

  // indexer  
  public short this[StabilityLevel stability, WindspeedClass windspeedClass, int direction]
  {
      get
      {                
          return _percentage[(int) stability][(int) windspeedClass][direction];
      }
      set
      {
          _percentage[(int)stability][(int)windspeedClass][direction] = value;
      }
  }  

  #endregion    

}
public class WindroseWindDirection : INotifyPropertyChanged
{
    private string _direction;
    private short _directionValue;

    #region Construction

    public WindroseWindDirection() : this("not available",0) {}

    public WindroseWindDirection(string direction, short defaultDirectionValue)
    {
        _direction = direction;
        _directionValue = defaultDirectionValue;
    }

    #endregion

    #region Properties

    public string Direction
    {
        get
        {
            return _direction;
        }
        set
        {
            if (String.Compare(_direction, value) != 0)
            {
                _direction = value;
                OnPropertyChanged("Direction");
            }

        }
    }
    public short DirectionValue
    {
        get
        {
            return _directionValue;
        }
        set
        {
            if (_directionValue != value)
            {
                OnPropertyChanged("DirectionValue");
                _directionValue = value;
            }                
        }
    }

    #endregion

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}
// just for reference: MVVM Light base view model class is used
public class AddModifyWindroseDialogViewModel : ViewModelBase
{
    #region Fields

    // holds the actual model class
    private Windrose _wr;
    // holds an ObservableCollection for each combination of StabilityLevel & WindspeedClass
    private ObservableCollection<WindroseWindDirection>[][] _dataGrid;
    // for Combobox
    private ObservableCollection<int> _numberOfDirectionValues = new ObservableCollection<int>(Constants.WindroseAllowedNumberOfDirections);    

    #endregion

        #region Construction

        public AddModifyWindroseDialogViewModel(Windrose windrose)
        {            
            _wr = windrose;            

            // create array[][] of observable collections, one for each stability <-> windspeed pair
            _dataGrid = new ObservableCollection<WindroseWindDirection>[Enum.GetNames(typeof(StabilityLevel)).Length][];
            int step = 360 / NumberOfDirections;
            foreach (StabilityLevel stability ... )
            {
                _dataGrid[(int) stability] = new ObservableCollection<WindroseWindDirection>[Enum.GetNames(typeof(WindspeedClass)).Length];
                foreach (WindspeedClass windspeed ... )
                {
                    _dataGrid[(int)stability][(int)windspeed] = new ObservableCollection<WindroseWindDirection>();
                    // Add 'No wind' special first row
                    _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection("No wind", _wr[stability, windspeed, 0]));
                    // Add the rest
                    for (int i = 0; i < NumberOfDirections; i++)
                    {
                        _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection(String.Format("{0} degrees", i * step), _wr[stability, windspeed, i + 1]));
                    }
                }
            }
        }

        #endregion

        #region Properties

        public String Name
        {
            get
            {
                return _wr.Name;
            }
            set
            {
                if (String.Equals(_wr.Name, value) == false)
                {
                    _wr.Name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        public int NumberOfDirections
        {
            get
            {
                return _wr.NumberOfDirections;
            }
            set
            {
                if (_wr.NumberOfDirections != value)
                {
                    _wr.NumberOfDirections = value;
                    RaisePropertyChanged("NumberOfDirections");
                    UpdateFilteredItems();
                }
            }
        }        
        public ObservableCollection<int> NumberOfDirectionsValues
        {
            get
            {
                return _numberOfDirectionValues;
            }
        }
        public StabilityLevel StabilityLevel
        {
            get
            {
                return _wr.StabilityLevel;
            }
            set
            {
                if (Enum.Equals(_wr.StabilityLevel, value) == false)
                {
                    _wr.StabilityLevel = value;
                    RaisePropertyChanged("StabilityLevel");
                    RaisePropertyChanged("FilteredItems");
                    RaisePropertyChanged("WindSpeedAverageClass1");
                    RaisePropertyChanged("WindSpeedAverageClass2");
                    RaisePropertyChanged("WindSpeedAverageClass3");                                        
                }
            }
        }
        public WindspeedClass Windspeed
        {
            get
            {
                return _wr.Windspeed;
            }
            set
            {
                if (Enum.Equals(_wr.Windspeed, value) == false)
                {
                    _wr.Windspeed = value;
                    RaisePropertyChanged("Windspeed");
                    RaisePropertyChanged("FilteredItems");
                }
            }
        }
        public ObservableCollection<WindroseWindDirection> FilteredItems
        {
            get
            {
                return _dataGrid[(int) StabilityLevel][(int) Windspeed];
            }
        }
        public float WindSpeedAverageClass1
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class1];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class1] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class1] = value;
                    RaisePropertyChanged("WindSpeedAverageClass1");
                }
            }
        }        
        public float WindSpeedAverageClass2
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class2];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class2] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class2] = value;
                    RaisePropertyChanged("WindSpeedAverageClass2");
                }
            }
        }
        public float WindSpeedAverageClass3
        {
            get
            {
                return _wr[StabilityLevel, WindspeedClass.Class3];
            }
            set
            {
                if (_wr[StabilityLevel, WindspeedClass.Class3] != value)
                {
                    _wr[StabilityLevel, WindspeedClass.Class3] = value;
                    RaisePropertyChanged("WindSpeedAverageClass3");
                }
            }
        }        

        #endregion

        private void UpdateFilteredItems()
        {
            /**/
            int step = 360 / NumberOfDirections;
            foreach (StabilityLevel stability ... )
            {                
                foreach (WindspeedClass windspeed ... )
                {
                    // Clear the old values
                    _dataGrid[(int)stability][(int)windspeed].Clear();                    
                    // Add 'No wind' special value
                    _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection("No wind", _wr[stability, windspeed, 0]));
                    // Add degrees
                    for (int i = 0; i < NumberOfDirections; i++)
                    {
                        _dataGrid[(int)stability][(int)windspeed].Add(new WindroseWindDirection(String.Format("{0} degrees", i * step), _wr[stability, windspeed, i + 1]));
                    }
                }
            }
            RaisePropertyChanged("FilteredItems");
        }                                            

}
<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>                

<Label Grid.Row="0" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Name" />
<TextBox Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />

<Label Grid.Row="1" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Number of directions" />
<ComboBox Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" SelectedItem="{Binding Path=NumberOfDirections, UpdateSourceTrigger=PropertyChanged}">
  <ComboBoxItem Content="4" />
  <ComboBoxItem Content="8" />
  <ComboBoxItem Content="12" />
  <ComboBoxItem Content="16" />
  <ComboBoxItem Content="36" />   
</ComboBox>

<Label Grid.Row="2" HorizontalAlignment="Left" ContentStringFormat="{}{0}:" Content="Stability Level" />
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Vertical">
  <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Unstable}}" Content="A - Unstable" />
  <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Neutral}}" Content="B - Neutral" />
  <RadioButton HorizontalAlignment="Left" IsChecked="{Binding Path=StabilityLevel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:StabilityLevel.Stable}}" Content="C - Stable" />
</StackPanel>

<Grid Grid.Row="3" Grid.ColumnSpan="2">                    
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>


  <TextBox Grid.Row="1" Grid.Column="1" Width="30" Text="{Binding Path=WindSpeedAverageClass2, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

  <RadioButton Grid.Row="0" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class1}}" Content="1 - 0 to 2 meters per second"  />
  <TextBox Grid.Row="0" Grid.Column="1" Width="30" Text="{Binding Path=WindSpeedAverageClass1, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

  <RadioButton Grid.Row="1" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class2}}" Content="2 - 2 to 4 meters per second" />
  <TextBox Grid.Row="1" Grid.Column="1" Width="30" Text="{Binding Path=WindSpeedAverageClass2, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

  <RadioButton Grid.Row="2" HorizontalAlignment="Left" IsChecked="{Binding Path=Windspeed, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:WindspeedClass.Class3}}" Content="3 - over 4 meters per second" />
  <TextBox Grid.Row="2" Grid.Column="1" Width="30" Text="{Binding Path=WindSpeedAverageClass3, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</Grid>

<!-- Here is the DataGrid. Please notice how ObservableCollection<WindroseWindDirection> is bound to the DataGrid ItemsSource and how individual columns are bound with properties of WindroseWindDirection  -->
<DataGrid Grid.Row="4" Margin="5" ItemsSource="{Binding FilteredItems}"  AutoGenerateColumns="False">
  <DataGrid.Columns>        
      <DataGridTextColumn Header="Wind Direction" Width="SizeToHeader" Binding="{Binding Direction}">
      </DataGridTextColumn>                          
      <DataGridTemplateColumn Header="Percent" Width="SizeToHeader">
          <DataGridTemplateColumn.CellTemplate>
              <DataTemplate>
                  <TextBox Text="{Binding DirectionValue, UpdateSourceTrigger=PropertyChanged}"/>
              </DataTemplate>                                
          </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>  

</Grid>