Am făcut o programare WPF și un lucru pe care nu l-am primit a fost modelul de comandă. Fiecare exemplu pare a fi pentru construit în unul, editați, tăiați, lipiți. Oricine are un exemplu sau sugestie de bune practici pentru comenzile personalizate?
Ah, ha! O întrebare pe care o pot răspunde! În primul rând, trebuie să menționez că mi-a fost mai ușor să definim și să conectăm mai mult comenzile în cod decât în XAML. Ea îmi permite să conectez manageri pentru comenzi mai ușor decât o abordare XAML.
Ar trebui să aflați ce comenzi doriți să aveți și la ce se referă. În aplicația mea, am în prezent o clasă pentru definirea unor comenzi importante de aplicație cum ar fi:
public static class CommandBank
{
/// Command definition for Closing a window
public static RoutedUICommand CloseWindow { get; private set; }
/// Static private constructor, sets up all application wide commands.
static CommandBank()
{
CloseWindow = new RoutedUICommand();
CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
//...
}
Acum, pentru că am vrut să păstrez codul împreună, folosind o abordare a codului numai pentru Comenzi îmi permite să pun următoarele metode în clasa de mai sus:
/// Closes the window provided as a parameter
public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e)
{
((Window)e.Parameter).Close();
}
/// Allows a Command to execute if the CommandParameter is not a null value
public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
e.Handled = true;
}
Cea de-a doua metodă poate fi împărtășită cu alte comenzi fără a fi nevoie să o repet peste tot.
Odată ce ați definit comenzile de acest fel, le puteți adăuga la orice bucată de interfață. In cele ce urmeaza, odata ce fereastra are Loaded, adaug legaturile de comanda la fereastra si MenuItem si apoi adaug un legare de intrare la fereastra folosind o buclă pentru a face acest lucru pentru toate legaturile de comenzi. Parametrul care este trecut este fereastra sa de sine astfel încât codul de mai sus știe ce fereastră să încerce și să închidă.
public partial class SimpleWindow : Window
{
private void WindowLoaded(object sender, RoutedEventArgs e)
{
//...
this.CommandBindings.Add(
new CommandBinding(
CommandBank.CloseWindow,
CommandBank.CloseWindowExecute,
CommandBank.CanExecuteIfParameterIsNotNull));
foreach (CommandBinding binding in this.CommandBindings)
{
RoutedCommand command = (RoutedCommand)binding.Command;
if (command.InputGestures.Count > 0)
{
foreach (InputGesture gesture in command.InputGestures)
{
var iBind = new InputBinding(command, gesture);
iBind.CommandParameter = this;
this.InputBindings.Add(iBind);
}
}
}
//menuItemExit is defined in XAML
menuItemExit.Command = CommandBank.CloseWindow;
menuItemExit.CommandParameter = this;
//...
}
//....
}
De asemenea, mai târziu am organizat evenimente pentru evenimentele WindowClosing și WindowClosed, vă recomand să faceți ca implementarea reală a comenzilor să fie cât mai mică și mai generică posibil. Ca și în acest caz, nu am încercat să pun cod care încearcă să oprească închiderea ferestrei dacă nu există date nesalvate, am păstrat acel cod ferm în cadrul evenimentului WindowClosing.
Dați-mi voie să știu dacă aveți întrebări ulterioare. :)
Lucrul cu XAML este că este bine pentru programele "simple", dar din păcate, nu funcționează bine atunci când doriți să faceți lucruri cum ar fi funcțiile de partajare. Spuneți că aveți mai multe clase și toate UI-urile care au comenzi care nu au fost niciodată dezactivate, va trebui să scrieți o metodă "CanAlwaysExecute" pentru fiecare fereastră sau UserControl! Nu este chiar foarte DRY .
După ce am citit mai multe bloguri și încercând mai multe lucruri, am făcut alegerea de a face XAML pur și simplu despre aspect, stiluri, animații și declanșatoare. Toată mișcarea legată de manipulatorii evenimentului și comandantul este acum în jos în codul din spate. :)
O alta miscare este legata de intrare, pentru a fi prinsi, trebuie sa se concentreze asupra obiectului care contine legaturile de intrare. De exemplu, pentru a avea o scurtă durată, puteți utiliza oricând (de exemplu, F1 pentru a deschide ajutor), că legarea de intrare trebuie să fie setată pe obiectul Window, deoarece întotdeauna se concentrează când aplicația este activă. Utilizarea metodei de cod ar trebui să facă acest lucru mai ușor, chiar și atunci când începeți să utilizați UserControls care ar putea dori să adauge legăturile de intrare la fereastra părinte.
I blogged about a bunch of resources on WPF Commands along with an example last year at http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx
Paste aici:
Adam Nathan?s sample chapter on Important New Concepts in WPF: Commands
Keyvan Nayyeri: Cum se adaugă comenzi la controlul WPF personalizat
Ian Griffiths: Intrarea, comenzile și manipulatorii Avalon
Bibliotecă MSDN: Prezentare comandă
Bibliotecă MSDN: Clasa CommandBinding
Bibliotecă MSDN: Subiecte de introducere și comandă în modul Cum să
Bibliotecă MSDN: Clasă de editare a comenzilor
Bibliotecă MSDN: Clasa MediaCommands
Bibliotecă MSDN: Clasa ApplicationCommands
Bibliotecă MSDN: Clasa NavigationCommands
Bibliotecă MSDN: ComponentCommands Class
Also buried in the WPF SDK samples, there's a nice sample on RichTextBox editing which I've extended. You can find it here: RichTextEditor.zip
În ediția din septembrie 2008 a revistei MSDN, Brian Noyes are un articol excelent despre RoutedCommand/RoutedEvents !!!
Here is the link: http://msdn.microsoft.com/en-us/magazine/cc785480.aspx