WPF数据网格根据选择的值生成行 [英] wpf datagrid generate rows according to a selected value

查看:133
本文介绍了WPF数据网格根据选择的值生成行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public enum StabilityLevel
{
    Unstable,
    Neutral,
    Stable
}

public enum WindspeedClass
{
    Class1,
    Class2,
    Class3
}

Windrose的

public class Windrose
{
        // percentual value for given direction
        private short[][][] _percentage;

        // average wind speed in wind speed classes        
        private float[][] _average;

        public Windrose()
        {            
            _percentage = new short[Enum.GetNames(typeof(StabilityLevel)).Length][][];
            foreach (StabilityLevel stability in EnumUtil.GetValues<StabilityLevel>())
            {
                _percentage[(int) stability] = new short[Enum.GetNames(typeof(WindspeedClass)).Length][];
                foreach (WindspeedClass windspeed in EnumUtil.GetValues<WindspeedClass>())
                {
                    // We reserve 0 for a special no-wind value, and we limit the maximum number of directions to 36 
                    _percentage[(int) stability][(int) windspeed] = new short[37]; 
                }
            }

            _average = new float[Enum.GetNames(typeof(StabilityLevel)).Length][];
            foreach (StabilityLevel stability in EnumUtil.GetValues<StabilityLevel>())
            {
                _average[(int) stability] = new float[Enum.GetNames(typeof(WindspeedClass)).Length];
            }    

            NumberOfDirections = 8;        
        }

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

        public short[] Percentage
        {
            get
            {
                return _percentage[(int) StabilityLevel][(int) Windspeed];
            }            
        }
        public float Average
        {
            get
            {
                return _average[(int) StabilityLevel][(int) Windspeed];
            }
            set
            {
                _average[(int)StabilityLevel][(int)Windspeed] = value;
            }
        }                                  
}

查看:

现在让我们来看看被用作一个模式窗口创建新WINDROSE这种观点(XAML):

View:

Now let's look at this view (xaml) that is used as a modal window for creating a new 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>

所以,每个稳定性级别'&LT; - >'风速阶级对,比如WINDROSE保持37值和一个额外的浮动值的数组

So for each 'stability level' <-> 'windspeed class' pair, the windrose instance keeps an array of 37 values and an extra float value.

我不知道该怎么做两件事情:

I don't know how to do 2 things:

我不知道如何创建该表(DataGrid中)。我希望能够改变被根据选定NumberOfDirections动态生成的行数。
所选NumberOfDirections也决定了两个连续行之间的台阶(360度被分成NumberOfDirections)。

I don't know how to create this table (DataGrid). I want to be able to change the number of rows that are generated dynamically according to the selected NumberOfDirections. The selected NumberOfDirections also determine the "step"(360 degrees is divided by NumberOfDirections) between two subsequent rows.

在用X格:NAME =WSClass我希望能够_average阵列的项目绑定到文本框,使每个对应一个特定的单选按钮文本框(即重新presents风速类)
具有价值_average [选择稳定性] [对应的单选按钮的风速。

In grid with x:Name="WSClass" I would like to be able to bind items of _average array to the TextBoxes so that each TextBox that corresponds to a certain RadioButton(that represents a wind speed class) has value _average[selected stability][windspeed of the corresponding RadioButton].

推荐答案

修改(2013年11月22日):

 我曾问一个相关问题一下这是如何裸力学来实现。
用户谢里登已经有回答了。正如我不能要求他到他的解决办法改写我的问题,这个问题的背景下(windroses)我决定这个回答是正确回答自己的问题,唯一的办法

EDIT (22.11.2013):
I have asked a related question about the bare mechanics of how this could be achieved. User Sheridan has answered it there. As I cannot ask him to rewrite his solution to my problem in the context of this question (windroses) I decided the only way to have this answered properly is to answer my own question.

警告:长岗

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    

}

视图模型类:

WindroseWindDirection

由于谢里登建议我创建了一个数据类型类认为我需要在一个DataGrid行显示的所有信息。

View Model classes:

WindroseWindDirection:

As Sheridan suggested I created a data type class to hold all information that I need to display in a datagrid row.

因此​​


  • 它实现 INotifyPropertyChanged的接口

  • 实现了每一列的属性,我想在DataGrid
  • 来显示


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
}

AddModifyWindroseDialogViewModel

有一个的ObservableCollection&LT; INT&GT; 组合框视图和的ObservableCollection&LT; WindroseWindDirection&GT; StabilityLevel &的每个组合LT; - > WindspeedClass 。由于用户必须能够一次我们创建了一个锯齿形数组它来编辑所有这些信息。

AddModifyWindroseDialogViewModel:

There is an ObservableCollection<int> for the ComboBox in the view and an ObservableCollection<WindroseWindDirection> for each combination of StabilityLevel <-> WindspeedClass. Because a user has to be able to edit all this information at once we create a jagged array for it.

基本上,想法是基于2属性决定了稳定水平,风速类的值,我们返回相应的的ObservableCollection&LT; WindroseWindDirection&GT; 通过第三个属性。如果用户更改为全WINDROSE方向的数量,我们会打电话给一个私有方法 UpdateFilteredItems()。有一个的ObservableCollection&LT; WindroseWindDirection&GT; 实际上允许我们将其绑定到的ItemsSource DataGrid的,随后定义的列DataGrid的自己和具有绑定到列 WindroseWindDirection 的各个属性。

Basically the idea is that based on the value of 2 properties that dictate the stability level and windspeed class we return the appropriate ObservableCollection<WindroseWindDirection> through third property. If the user changes the number of directions for the whole windrose, we'll call a private method UpdateFilteredItems(). Having an ObservableCollection<WindroseWindDirection> actually allows us to bind it to the ItemsSource of the DataGrid and subsequently define the Columns of DataGrid ourselves and have the individual properties of WindroseWindDirection bound to the columns.

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

这篇关于WPF数据网格根据选择的值生成行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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