Skip to content

Forum

Please or Register to create posts and topics.

Ottenere l'oggetto contenuto in una cella di un Datagrid WPF

Ciao

Come da oggetto, voi come fate?

Tenendo conto che:

1 - Ogni cella puo' contenere un oggetto di cui ignoro il tipo.

2 - Ogni riga puo' contenere un oggetto differente di cui ignoro il tipo.

Sembra assurdo ma e' così 😉

Parlo solo per la Datagrid di WPF, non Winform o Syncfusion.

 

sabrina_c has reacted to this post.
sabrina_c

Indipendentemente dalla Datagrid che usi, una Grid WPF ha una property ItemsSource a cui assegni la collection che visualizzi
Quindi gli oggetti ce li hai già. Perché usualmente metti in Binding sull'oggetto CurrentItem o SelectedItem che trovi sempre sulla Datagrid un opportuna property del tuo datacontext.

Pertanto l'oggetto correntemente attivo ce lo hai di certo.

Se gli oggetti sono eterogenei e li vedi nella grid, di ciascun oggetto vedi il risultato del metodo ToString della classe.

Se sono Interfacce, comunque tornando al CurrentItem o SelectedItem puoi ottenere quello che vuoi.

Se non ti serve l'oggetto presente nella riga ma il contenuto della cella attiva puoi implementare questo event handler:

private void GrActivities_CurrentCellChanged(object sender, EventArgs e)
		{
			try
			{
				DataGrid grid = sender as DataGrid;
				if (grid != null)
				{
					if (grid.CurrentCell.Item is ActivityItem)
					{
						CurrentActivity = grid.CurrentCell.Item as ActivityItem;
					}
 
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString(), "ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);
			}
 
		}
Ho il sospetto
che l'oggetto CurrentCell ti permetta l'accesso non solo all'Item collegato ma anche al contenuto della cella.

Saluti

Grazie

Il codice che mi hai girato lo ho già piu' o meno testato ma non fa al caso mio, almeno in questa situazione, in quanto tutta la Grid e' generata da oggetti annidati e non da oggetti con relative property.

Questa che mi indichi sarebbe la parte di codice fondamentale:

CurrentActivity = grid.CurrentCell.Item as ActivityItem;

Che però restituisce l'oggetto in binding con la riga e non con la cella.

Se avessi una classe ActivityItem mi basterebbe recuperare il valore della property interessata da CurrentActivity come tu indichi.

Nel mio caso non ci sono property ma solo oggetti che sono stati messi in binding via codice  in n DataGridBoundColumn le quali vengono "costruite" con altri valori di settings recuperati per generarle.

Finora sfruttavo il nome degli Header per recuperare l'oggetto con un codice tipo questo:

CurrentRow = grid.CurrentCell.Item as MyClass;

CurrentActivity = CurrentRow[Header.ToString()];

Ma visto che ho introdotto i settings per poter modificare appunto il testo dell'header, ora tale testo puo' non combaciare con l'oggetto da recuperare.

La soluzione che tenterò e' un'altra.

Ovvero creare un binding anche per l'Header il cui oggetto conterrà sia il testo da visualizzare che il testo utile per cercare l'oggetto contenuto nella cella.

Avrei preferito una strada piu' "leggera" ma non trovo come recuperare il valore della cella con altri metodi.

 

 

Ho verificato che  usando questo:

grid.CurrentCell.Column.Header

Header è un object, pertanto se usi un oggetto per l'header in cui metti la property con il titolo e la property
con il nome del campo, usando il Tostring x restituire il titolo la colonna dovrebbe essere riportata
correttamente e dall'oggetto header puoi ricavare quello che ti serve.

Ovviamente se insisti ad usare la grid standard, io uso la grid Syncfusion che oltre a fornirmi il modo per risalire
direttamente all'oggetto nella cella e ha già i dati relativi al mapping nei dati della colonna.

saluti

Certo

Ma come dicevo uso oggetti generici e quindi non ho specifiche property a cui fare riferimento.

Diciamo che sto realizzando una grid che eredita da DataGrid  per un framework basato su oggetti di dati gerarchici generici .

Usare la grid di Syncfusion mi vincolerebbe a tale azienda.

Per intenderci, i miei dati sono tutti (ho semplificato la classe):

MyClass

{

string Key{get;set}

object Value{get;set}

}

Quindi:

MyClass1.Key = "Nome_Colonna"

MyClass1.Value= ObservableCollection<MyClass>

MyClass1.Value[0].Key = "Header"

MyClass1.Value[0].Value= "Nome Colonna"

MyClass1.Value[1].Key = "Type"

MyClass1.Value[1].Value= "ComboBox"

 

Quindi dovrei passare alla DataGridColumHeader l'oggeto MyClass1  il quale però, con il metodo ToString() non restituisce "Nome Colonna".

Facendo come dici tu, dovrei creare una classe MyHeader(MyClass myClass) con override del ToString() che restituisce MyClass.Value["Header"] e passarla a DataGridColumnHeader.

Certamente si puo' fare ma questo mi vincola a creare una classe MyHeader e quindi poi dovrei creare mille altre classi per ogni setting da gestire.

Se trovo il modo di risolvere la path, credo sia piu' elegante e generico qualcosa del genere:

var path = ??;  //Trovare quale sia la Path da assegnare per recuperare il figlio con l'header. Tipo "MyClass["Header"].Value"
var binding = new Binding(path);
binding.Source = MyClass1 ;
BindingOperations.SetBinding(this, DataGridBoundColumn.HeaderProperty, binding);

Questo perche', risolvendo questa situazione, risolvo anche tutti gli altri possibili binding futuri nel caso volessi impostare altri settings partendo dalla struttura dati che sto utilizzando.

Ora devo capire come risolvere la path.

 

 

 

 

 

Per chiudere il post ho risolto in un altro modo anche se non sono contento

La mia grid usa colonne che ereditano da DataGridBoundColum

Detto ciò, e' stato molto semplice aggiungere una proprietà RawColumName alla MyColumn e quindi:

var key = column.RawColumnName;
selectedItem = SelectedItem as MyClass;
currentCell = selectedItem[key];

Per quando riguarda il sistema per risolvere la path di un binding (per come serve a me), indagherò meglio, ma dalle prime ricerche non sembra possibile.

Solo una risposta tecnica,

il Forum è molto semplice, il moderatore non "chiude" i post.

Il moderatore interviene solo se i post sono giudicati non pertinenti o se il contenuto è offensivo.

saluti