Binding między obiektem i DataGrid

0

Cześć,

mam klasę, w której znajduje się kilka wartości string i lista. Chciałbym wyświetlić ją na DataGrid, jednak nie mogę tego zrobić właśnie ze względu na tą listę. Mam dwa pomysły, jak to rozwiązać:

  • utworzyć drugi DataGrid do wyświetlania elementów listy - w momencie, gdy użytkownik zaznaczy obiekt (wiersz), który ma listę różną od null, aktywny stawałby się drugi DataGrid (zobrazowałem to na załączonym schemacie)
  • użyć czegoś innego zamiast DataGrid (czego?) - w tej sytuacji, gdy użytkownik zaznaczyłby taki obiekt, który ma listę różną od null, wyświetlałaby się zagnieżdżona część DataGrid (podejrzewam, że byłoby to trudniejsze do zrealizowania, niż pierwsza możliwość)

W jaki sposób mogę utworzyć binding pomiędzy takim obiektem klasy zawierającej listę innych obiektów?

Aktualnie otrzymuję wyjątek:

StackOverflowException was unhandled
An unhandled exception of type 'System.StackOverflowException' occurred in WpfApplication1.exe

  • $exception	{Cannot evaluate expression because the current thread is in a stack overflow state.}	System.Exception {System.StackOverflowException}
    this	null	WpfApplication1.Parameters
    value	Cannot obtain value of local or argument 'value' as it is not available at this instruction pointer, possibly because it has been optimized away.	System.Collections.Generic.List<string>
    

Następuje on w tym miejscu:

        #region Properties
        public string ParameterName { get; set; }
		public string DefaultValue { get; set; }
        public ExternTypes ParameterType { get; set; }
        public List<String> EnumValues
        {
            get
            {
                return EnumValues;
            }
            set
            { // nieobsłużony wyjątek
                EnumValues = value;
            }
        }
        #endregion

Zaś obiekt wiążę z DataGrid w ten sposób:

            // utwórz testowy obiekt i powiąż z DataGrid
            Settings testSettings = new Settings("Test");
            myTestScenarioUC.dgrNumericalParameters.ItemsSource = testSettings.Parameters;

Cały projekt również w załączniku. Usunąłem z niego wszystkie części, które nie są związane z problemem, jednak z zachowaniem struktury mojego programu.

Pozdrawiam!

1

Że coś takiego ?

C# code:

public partial class MainWindow : Window
    {
        DataTable dt = new DataTable();
        public MainWindow()
        {
            InitializeComponent();
            dt.Columns.Add("AA", typeof(string));
            dt.Columns.Add("BB", typeof(string));
            dt.Rows.Add("11", "22");
            dt.Rows.Add("33", "44");
            this.dataGrid1.DataContext = dt;
            this.dataGrid1.RowDetailsVisibilityChanged += new EventHandler<DataGridRowDetailsEventArgs>(dataGrid1_RowDetailsVisibilityChanged);
        }
        void dataGrid1_RowDetailsVisibilityChanged(object sender, DataGridRowDetailsEventArgs e)
        {
            DataGrid innerDataGrid = e.DetailsElement as DataGrid;
            innerDataGrid.ItemsSource = ((IListSource)dt).GetList();
        }
    }

XAML code:

	
<DataGrid    Name="dataGrid1" ItemsSource="{Binding}">
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <DataGrid Name="innerGrid"></DataGrid>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

Źródło: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8f368d8b-0d06-4219-80f8-e8108f219fc2/

A co do Twojego błędu Twój set i get powinny wyglądać następująco:

        private List<String> enumValues;
        public List<String> EnumValues
        {
            get
            {
                return enumValues;
            }
            set
            { // nieobsłużony wyjątek
                enumValues = value;
            }
        }

lub

public List<String> EnumValues { get; set; }
0

Dzięki,

to jest dokładnie to, czego potrzebowałem :).

Aktualnie usiłuję wykonać binding pomiędzy listą (czyli elementami enumeracji, które użytkownik ma dodawać i usuwać) a innerDataGrid.

W ten sposób mogę się dostać do tej listy z wartościami definiowanymi przez użytkownika:

EAsSettings testTest = allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName);
EAParameters testTest2 = testTest.EAParameters.Find(item3 => item3.ParameterName == firstColumn);

Tak mogę przypisać listę do innerDataGrid, ale otrzymuję niewłaściwe wartości:

innerDataGrid.DataContext = allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues; // it can access EnumValues but shows those improperly

Listę mam zdefiniowaną tak:

        public List<String> EnumValues
        {
            get
            {
                return enumValues;
            }
            set
            {
                enumValues = value;
            }
        }

Zatem próbuję zamienić EnumValues na IListSource

innerDataGrid.DataContext = ((IListSource)allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues).GetList();

Jednak otrzymuję wyjątek:

InvalidCastException was unhandled:
Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.ComponentModel.IListSource'.

Próbuję teraz osiągnąć to, żeby móc prawidłowo przypisać EnumValues do DataContext. Na to zamierzam poświęcić najbliższy czas, jeśli jednak masz jakieś sugestie, które mogłyby mnie przybliżyć do tego celu, to będę za nie wdzięczny.

Pozdrawiam!

1

Trochę ci się namieszało :P innerDataGrid.DataContext powiązujesz z obiektem allEAsSettings
a potem wyciągasz to co potrzebujesz do ItemsSource. Więc coś takiego:

innerDataGrid.DataContext = allEAsSettings;
innerDataGrid.ItemsSource = ((IListSource)allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues).GetList();
1

Okej to jak masz zdefiniowanego DataGrida?

Ma na myśli w xamlu masz coś takiego:

DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding ID}"  Header="ID" Width="50"
                                        IsReadOnly="True" />
i tak dalej...

czy w dodajesz w kodzie ?

Ale do czego zmierzam co się pokazuje jak byś zrobił tak że masz sam ItemSource i Autoregeneracje włączoną w DataGridzie?

<DataGrid AutoGenerateColumns="True" Name="dataGrid1" ItemsSource="{Binding}">
...
0

Cześć,

DataGrid jest zdefiniowany w ten sposób:

<DataGrid Grid.Row="8" Grid.Column="0" Margin="5" Grid.ColumnSpan="3" Name="dgrNumericalParameters" ItemsSource="{Binding}">
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <DataGrid AutoGenerateColumns="True" Name="innerGrid" ItemsSource="{Binding}"></DataGrid>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

Obiekt wiążę z DataGrid poprzez:

myTestScenarioUC.dgrNumericalParameters.DataContext = testEAsSettings.EAParameters;

Natomiast powiązanie innerDataGrid:

innerDataGrid.DataContext = allEAsSettings;
//innerDataGrid.ItemsSource = ((IList<String>)allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues);
innerDataGrid.ItemsSource = ((IListSource)allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues).GetList();

Kod z rzutowaniem na (IListSource) powoduje wspomniany wcześniej wyjątek. Rzutowanie na IList<String> wyświetla dane w sposób nieprawidłowy, tj. pojawiają się wartości Length (niezależnie od umieszczenia AutoGenerateColumns="True").

Pozdrawiam!

1
innerDataGrid.DataContext = allEAsSettings;
innerDataGrid.ItemsSource = allEAsSettings.Find(item2 => item2.EAName == currentEAsSettingsName).EAParameters.Find(item3 => item3.ParameterName == firstColumn).EnumValues.ToList().Select(x => new { x });

o to się rozchodzi ? :P

A czemu tak a nie inaczej ponieważ string posiada tylko jedno public property długość i przy auto generacji dataGrid tylko to wyciągał.

1 użytkowników online, w tym zalogowanych: 0, gości: 1