none
Отображение списка элементов со сложной структурой RRS feed

  • Вопрос

  • Имеется список List<OptionCombination> Combos, который необходимо вывести. Класс OptionCombination обладает следующей структурой:

    class OptionCombination
    {
      public Portfolio _Portfolio { get; set; }
      public List<ExtendedPosition> ComboElements { get; set; }
      public HedgingMethod HedgeMethod { get; set; }
      public Greeks SumGreeks { get; set; }
      public bool IsHedging { get; set; }
    }
    class Portfolio
    {
      public string Name {get;set;}
      public decimal Balance {get;set;}
    }
    class ExtendedPosition
    {
      public Position position { get; set; }
      public long InUse { get; set; }
      public Greeks _Greeks { get; set; }
      public Greeks SumGreeks { get; set; }
    }
    class Position
    {
      public long CurrentAmount {get;set;}
      public Portfolio _Portfolio {get;set;}
      public string Security {get;set;}
    }
    struct Greeks
    {
      public decimal delta;
      public decimal vega;
      public decimal theta;
    }


    Для вывода одного элемента у меня имеется шаблон элементов управления, выглядит он примерно вот так:

    Как реализовать вывод так , чтобы при каждом элементе Combos выводился приведенный выше GroupBox, с привязанными данными.  Т.е. Name - это OptionCombination.Portfolio.Name, Security - ExtendedPosition.Position.Security и т.д. Я не привожу всей структуры, дабы не захламлять топик, но примерно как это выглядит вроде видно.

    Самая большая сложность для меня на данный момент - как реализовать привязку, где нужно обращаться к вложенным полям класса.

    Посоветуйте, как лучше реализовать отображение этого списка.

     




    • Изменено Dottz 13 декабря 2011 г. 7:12
    13 декабря 2011 г. 7:07

Ответы

  • > для WPF


    примерно так:
    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="500" FontSize="16">
        <StackPanel>
            <ComboBox ItemsSource="{Binding Combos}" IsSynchronizedWithCurrentItem="True" 
                      DisplayMemberPath="_Portfolio.Name"
                      x:Name="cb" />
            <GroupBox DataContext="{Binding ElementName=cb, Path=SelectedItem}" Header="{Binding _Portfolio.Name}">
                <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding ComboElements}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding position.Security}" Header="Security" />
                        <DataGridTextColumn Binding="{Binding InUse}" Header="InUse" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.delta}" Header="Delta" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.theta}" Header="Theta" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.vega}" Header="Vega" />
                    </DataGrid.Columns>
                </DataGrid>
            </GroupBox>
        </StackPanel>
    </Window>
    
     
     
    для того чтобы работала привязка SumGreeks
    надо изменить определение Geeks на следующее:
     
    class Greeks
    {
        public decimal delta { get; set; }
        public decimal vega { get; set; }
        public decimal theta { get; set; }
    }
    
      
    • Помечено в качестве ответа Dottz 14 декабря 2011 г. 10:49
    13 декабря 2011 г. 14:47
  • > привязка не осуществляется. [...] this.Positions = new ObservableCollection<ExtendedPosition>();
     
     
    чтобы данные стали видны контролам, надо в конструкторе указать, например:
    this.DataContext = new ObservableCollection<ExtendedPosition>();
    
    

    если в xaml:
    <DataGrid ItemsSource="{Binding Positions}" ...
    

    т.е. DataGrid ожидает получить объект, со свойством Positions -> коллекция, то в конструкторе надо указать:
    this.DataContext = new { Positions = new ObservableCollection<ExtendedPosition>() };
    
    
     
     
    • Помечено в качестве ответа Dottz 16 декабря 2011 г. 8:37
    16 декабря 2011 г. 7:21

Все ответы

  • > как лучше реализовать отображение этого списка.
     
     
    для WPF или WinForms? данные хранятся в xml или в бд?
     
     
    13 декабря 2011 г. 9:42
  • для WPF. Список формируется на лету и висит в памяти, нужды писать в XML нету, т.к. список небольшой ~ 10 элементов.
    13 декабря 2011 г. 9:46
  • > для WPF


    примерно так:
    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="500" FontSize="16">
        <StackPanel>
            <ComboBox ItemsSource="{Binding Combos}" IsSynchronizedWithCurrentItem="True" 
                      DisplayMemberPath="_Portfolio.Name"
                      x:Name="cb" />
            <GroupBox DataContext="{Binding ElementName=cb, Path=SelectedItem}" Header="{Binding _Portfolio.Name}">
                <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding ComboElements}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding position.Security}" Header="Security" />
                        <DataGridTextColumn Binding="{Binding InUse}" Header="InUse" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.delta}" Header="Delta" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.theta}" Header="Theta" />
                        <DataGridTextColumn Binding="{Binding SumGreeks.vega}" Header="Vega" />
                    </DataGrid.Columns>
                </DataGrid>
            </GroupBox>
        </StackPanel>
    </Window>
    
     
     
    для того чтобы работала привязка SumGreeks
    надо изменить определение Geeks на следующее:
     
    class Greeks
    {
        public decimal delta { get; set; }
        public decimal vega { get; set; }
        public decimal theta { get; set; }
    }
    
      
    • Помечено в качестве ответа Dottz 14 декабря 2011 г. 10:49
    13 декабря 2011 г. 14:47
  • Спасибо, опробую
    14 декабря 2011 г. 10:52
  • Пытаюсь привязать просто список из ExtendedPosition , но чтобы datagrid сам обновлялся List я заменил на ObservableCollection. Сделал как вы писали, но привязка не осуществляется. Объявление Greeks тоже поменял.

    XAML:

    <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding Positions}">
     <DataGrid.Columns>
      <DataGridTextColumn Binding="{Binding position.Security}" Header="Security" />
      <DataGridTextColumn Binding="{Binding position.CurrentAmount}" Header="Amount" />
      <DataGridTextColumn Binding="{Binding InUse}" Header="InUse" />
      <DataGridTextColumn Binding="{Binding SumGreeks.delta}" Header="Delta" />
      <DataGridTextColumn Binding="{Binding SumGreeks.theta}" Header="Theta" />
      <DataGridTextColumn Binding="{Binding SumGreeks.vega}" Header="Vega" />
     </DataGrid.Columns>
    </DataGrid>
    

    Code:

    public partial class MainWindow : Window
    {
     public ObservableCollection<ExtendedPosition> Positions {get; set;}
     public MainWindow()
       {
         InitializeComponent();
         this.Positions = new ObservableCollection<ExtendedPosition>();
    
       }
    }
    
    
     

    16 декабря 2011 г. 7:03
  • > привязка не осуществляется. [...] this.Positions = new ObservableCollection<ExtendedPosition>();
     
     
    чтобы данные стали видны контролам, надо в конструкторе указать, например:
    this.DataContext = new ObservableCollection<ExtendedPosition>();
    
    

    если в xaml:
    <DataGrid ItemsSource="{Binding Positions}" ...
    

    т.е. DataGrid ожидает получить объект, со свойством Positions -> коллекция, то в конструкторе надо указать:
    this.DataContext = new { Positions = new ObservableCollection<ExtendedPosition>() };
    
    
     
     
    • Помечено в качестве ответа Dottz 16 декабря 2011 г. 8:37
    16 декабря 2011 г. 7:21
  • А как автоматически обновлять Control, если я привязываю не к коллекции а к объекту? Каждый раз обновлять DataContext?
    16 декабря 2011 г. 8:37
  • > А как автоматически обновлять Control, если я привязываю не к коллекции а к объекту? Каждый раз обновлять DataContext?


    создать объект с интерфейсом INotifyPropertyChanged, примерно так:
    class Data : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
       ...
    
    

    пример здесь. или другой вариант: создать TypeDescriptionProvider; пример здесь.
     
     
    • Изменено Malobukv 16 декабря 2011 г. 8:49
    16 декабря 2011 г. 8:48
  • Только сейчас заметил одну вещь в вашем коде:

    <ComboBox ItemsSource="{Binding Combos}" IsSynchronizedWithCurrentItem="True" 
                      DisplayMemberPath="_Portfolio.Name"
                      x:Name="cb" />

    Он, как я понимаю, заточен под то, что пользователь будет из комбобокса выбирать какой из ComboElements ему надо отобразить. Мне же надо, чтобы выводились сразу все элементы и каждый отображался выше приведенной "формой". Как-то так... Я сначала что-то не углядел, а как начал плотнее заниматься этим, так и понял, что вроде не то =)

    16 декабря 2011 г. 13:06
  • > Мне же надо, чтобы выводились сразу все элементы и каждый отображался выше приведенной "формой".


    вместо ComboBox можно указать ListBox.

    16 декабря 2011 г. 13:22