C# wpf datagrid根据选定的值生成行 型号: 枚举: 温德罗斯: 视图:
现在让我们看看这个视图xaml,它被用作创建新windrose的模式窗口: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
<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>