Sincronizzare context menu del treeview e toolbar

giovedì 28 marzo 2013 - 11.19
Tag Elenco Tags  C#  |  .NET 4.0  |  Windows 7  |  Visual Studio 2010  |  SQL Server 2008 R2

stee85 Profilo | Senior Member

Ciao,
ho un treeview, per ogni nodo devo creare un context menu costituito dai seguenti menu:
- Pulsante 1 (varia da nodo a nodo)
- Pulsante 2 (varia da nodo a nodo)
- Expand (su tutti i nodi)
- Collapse (su tutti i nodi)
- Refresh (su tutti i nodi)

E' possibile compilare la toolbar con gli stessi menu del context con un binding o qualche cosa di simile?
Posso evitare di riscrivere su ogni context menu i menu statici (expand, collapse..)?

Grazie
Ste

0v3rCl0ck Profilo | Guru

>Ciao,

Ciao

>ho un treeview, per ogni nodo devo creare un context menu costituito
>dai seguenti menu:
>- Pulsante 1 (varia da nodo a nodo)
>- Pulsante 2 (varia da nodo a nodo)
>- Expand (su tutti i nodi)
>- Collapse (su tutti i nodi)
>- Refresh (su tutti i nodi)

La treeview è fissa, o generata dinamicamente da dati con binding o altro?

>
>E' possibile compilare la toolbar con gli stessi menu del context
>con un binding o qualche cosa di simile?

direi di si, sfruttando il binding come hai detto, partendo però dal fatto di avere un buon ViewModel alla base, in modo da poterlo sfruttare come datacontext/itemssource sia del context menu che della toolbar, generando di fatto gli stessi elementi.

>Posso evitare di riscrivere su ogni context menu i menu statici
>(expand, collapse..)?

Questo si dovrebbe riuscire ad ottenere con un template oppure sfruttando il ViewModel che come base restituisca sempre un certo numero di elementi.

>
>Grazie
>Ste

di niente :)


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

stee85 Profilo | Senior Member

Ciao

>La treeview è fissa, o generata dinamicamente da dati con binding
>o altro?

La treeview la compilo dinamicamente facendo binding ad un ObservableCollection
Ho uno hierarchicaltemplate per creare i vari nodi

>>E' possibile compilare la toolbar con gli stessi menu del context
>>con un binding o qualche cosa di simile?
>
>direi di si, sfruttando il binding come hai detto, partendo però
>dal fatto di avere un buon ViewModel alla base, in modo da poterlo
>sfruttare come datacontext/itemssource sia del context menu che
>della toolbar, generando di fatto gli stessi elementi.

Si può fare anche senza l'utilizzo del ViewModel?

Ste

0v3rCl0ck Profilo | Guru

Intanto per evitare di riscrivere ogni singolo context menu a mano puoi fare così:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Per quanto riguarda tenere allineato un context menu ad una status bar, mi verrebbe da dire che una base dati ci serve, che poi non sia un ViewModel, ma una collezione istanziata sulla vista stessa o nel code-behind, è uguale, ma così su due piedi la domanda è "c'è un metodo per scorrere il visual tree da xaml per ciclarlo e recuperare le proprietà con un binding?" ok per leggere le proprietà di un altro controllo con il binding non c'è nessun problema, ma esiste il modo di impostare l'ItemSource o comunque un Source agli elementi contenuti nel visual tree di un ContextMenu? Non credo di averci mai provato, ma è la volta buona, fammici pensare un po'...


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

0v3rCl0ck Profilo | Guru

Ok, ho trovato anche il modo di "attaccarsi" agli elementi di un altro controllo, "rubandogli" la lista dei suoi items, e lo si può fare anche prendendo gli elementi da una risorsa, infondo non sono altro che oggetti che vengono istanziati nel momento in cui si istanzia la View, tra l'altro è possibile anche controllare il metodo di istanziazione delle risorse con la proprietà x:Shared="True/False", se impostata a True la risorsa viene istanziata una volta per tutta la vita della View, viceversa viene istanziata ogni volta che viene utilizzato il riferimento {StaticResource ...}

e quindi dicevo, non ho fatto altro che bindare la lista degli items all'ItemsSource della statusbar attraverso una compositeCollection contenente un CollectionContainer che supporta il binding, poi con un DataTemplate impostato sull'ItemTemplate, ho creato il template leggendo come dato le proprietà del MenuItem del ContextMenu. Se non si specifica un ItemTemplate, dato che un MenuItem può essere messo anche nella status bar, ti ritroverai esattamente lo stesso identico elemento anche nella StatusBar, ma credo che l'aspetto di una StatusBar si voglia diversificare:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Sinceramente non so se sia l'unico modo per farlo, non lo trovo particolarmente elegante, ma neanche particolarmente rozzo, alla fine stiamo facendo quello che si farebbe in code-behind se appunto non si avesse a disposizione una collezione con i dati, ma solo il ContextMenu già riempito, da cui dobbiamo estrargli i dati.

Diciamo che forse è un po' una forzatura io definirei i due stili, uno per il ContextMenu e l'altro per lo StatusBar, senza questi sofisticatismi, però senza dilungarmi troppo, mi hai chiesto se c'era la possibilità, e in effetti si, può, fareeee :)


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

stee85 Profilo | Senior Member

Ciao, grazie mille per l'aiuto.
Sto provando ad implementare la tua soluzione ma ho qualche problemino.. questo è il mio codice

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

2 problemi:
1. quando clicco con il tasto destro sul nodo del treeview compare il context menu ma scompare la toolbar
2. Sulla toolbar vorrei mostrare solo l'icona e collegare l'evento, ma anche se modifico il datatemplate della toolbar Content="{Binding Path=Header}" in Content="{Binding Path=Icon}" non cambia niente.. mi mostra sempre icona + testo

EDIT:
Per mostrare/nascondere i menu a seconda del nodo del treeview pensavo di fare una cosa del genere nel contextmenu
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Ma a quanto pare il Treeview non esiste ancora in questo punto e va in errore..


grazie
Ste

0v3rCl0ck Profilo | Guru

Per la sparizione della toolbar prova a mettere x:Shared="False" sulla risorsa contextmenu, ho paura che utilizzo lo stesso elemento grafico e che lo sposta invece che crearne uno nuovo... Al massimo troviamo un'altra soluzione anche perché questa non mi piace particolarmente


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

stee85 Profilo | Senior Member

Ciao, grazie! Così funziona perfettamente.
Mi manca solo da differenziare lo stile tra toolbar e treeview context menu e poi sono a posto.
Riusciresti a postarmi un esempio?
grazie mille
Ste

0v3rCl0ck Profilo | Guru

puoi personalizzare come vuoi la toolbar, perchè i due elementi (toolbar e contextmenu) sono completamente slegati tra loro, in pratica noi non abbiamo fatto altro che collegarci alla lista degli elementi di una nuova istanza del contextmenu, giusto per riutilizzare gli elementi già scritti dentro di esso, anche se come ti dicevo lo trovo un po' una forzatura, il giusto sarebbe stato avere una lista a ViewModel collegata per entrambi gli elementi. In altre parole è come se avessimo fatto un array di stringhe nelle risorse ed entrambi i controlli l'avessero utilizzato come ItemsSource, quindi in pratica la tua ToolBar può essere personalizzata come vuoi:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

puoi cambiare il DataTemplate con quello che vuoi, e cambiare qualsiasi stile senza paura di andare a toccare quello del ContextMenu e viceversa.

ti lascio anche l'esempio con un array creato nelle risorse che viene utilizzato come ItemsSource per entrambi i controlli:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

qui ho creato un array di stringhe, con la stessa idea è possibile creare array di tue classi custom con più proprietà.

ciao!

-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5