Jak dodać przenoszenie okien Drag&Drop?

Jak dodać przenoszenie okien Drag&Drop?
MD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10
0

Hej,

potrzebuję zbudować aplikację wpf z wykorzystaniem mvvm na .net8. Ale w założeniach jest wymóg żeby okna używane w aplikacji były typu drag and drop.
dlatego szukam jakieś przyjaznej biblioteki, którą mógłbym użyć lub może możecie polecić jakiś tutorial, który mnie by w to wprowadził.

To jedna z moich pierwszych projektów z wpf-em i do tego tak duży.

w swoich poszukiwaniach natknąłem się na przykłady Dirkster.AvalonDock ale nie mogę znaleźć przykładów nowszych niż framework 4.8. a znaleziona tam dokumentacja jest dla mnie mało czytelna lub pomija początki.

Będę wdzięczny za pomoc :)

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
1

Może coś się zmieniło w ostatnich kilkulatach ale na 85% nie znajdziesz dobrego darmowego rozwiązania i zawsze będzie jakiś kompromis lub coś nie jasnego. Komercyjne też nie napawają mnie optymizmem, ale moze jakieś fajne są. Możesz napisać to sam. Cały trick polega na tym żeby napisać dwie klasy, swoje okono, i swój komponent(czasem jest 3 z głowna treścia programu), dopisać w nich eventy na drag drop, jesli dane z drag drop sa dobrego typu, wyświetlasz te kwadraciki.
Samo przemieszczanie kontrolek, okien mozesz zrobić tak, że zdejmujesz kontrolkę z parenta, i podpinasz do drugiego. Nigdy jej nie usuwasz.
Dobrym protipem moze być też zeby nie siłować sie z koniem i guziki, Zamknij, minimalizuj, przypnij, itp. napisac własne, tak to ma zrobiony google, chrome, visula studio, word, w zasadzie każda aplikacja. Jest jakis interfejs na to, ale nazywa się "Chrome' stąd google chrom i jest absolutnie nie googlowalny.

Ogólnie zadanie jest upierdliwe ale stosunkowo proste, przy pewnej biegłości prototyp można zrobić w dzień. To co jest upierdliwe i istotne, to przemyśleć upewnic sie okolejności wysyłania eventow, statatusie aktywnego okna, itd. Osobiście jeśli to nie jest projekt osobisty tylko do corpo, polecił bym Ci pisać eventy na kazdą zmiane stanu. beforeActivation, Activating, AfterACtivated, bo lepiej jest mieć przemyślaną nadmiarowość niz minimalistyczny model, który wymusi tygodnie roboczo pisania haków, bo coś nie bangla.

Jedyną rzecza która wymaga dokładnych instrukcji to napisanie tych bazowych kontrolek tak by były równie ładne co fabryczne. Tak żeby xaml pisało sie tak

Kopiuj
<mojeOkno>
  <grid>
    <textbox. działa jak nomalna kontrolka a nie pokracznie <textbox>
  </grid>
</mojeOkno>

Jakoś to wygooglujesz.
Ostatnią radą, nie pisz na siłe wszystkieo w xamlu. Kazda walka z frameworkiem, lub wewnetrzna logika kontrolki/okna ma prawo być code behind.

.

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
0

Jak patrzę ile tekstu wyszło, to jest to więcej roboty, niż chop siup dzień dwa :P, ale ciągle jest to w kategorii realne do wyklepania.

Większość aplikacji rozwiązuje podobne problemy pisząc singletona reprezentującego stan całej aplikacji. Ribbon, okna, status bark, commendy, toole itp. itd.
Ty masz chyba tylko okna ale i tak zaczął bym właśnie od takiej wydmuszki na wejściu. Nic to nie kosztuje i się nie zakopiesz.
Publiczny interfejs w tych warstwach pisał bym na interfejsach, bo istnieje smutna tendencja do tego ze kod jest użyty 2000 razy i nie da się już poprawić, np. implementacji z listy na hash set.

Klasa od okienek powinna posiadać kolekcje okien. Aktywne okno, eventy na przed po na zmianę: aktywnego okna, zamilkniecie, otwarcie. Itp. oraz metody, otwórz zamknij okno/ dialog.
Bardzo przydatne będzie jeśli każde okno będzie miało własny unikalny indetyfikator.
Metoda do otwierania okienek wyglądała by przykładowo tak ITwójInterfejsOkna OpenToolWIndow(string title, string id, IFrameworkElement element , ITwójInterfejsOkna parent = null). Zamiast IFrameworkElement możesz dać dowolny inny interfejs WPF lub własny który da się wyświetlić w kontrolce.

Nie głupim pomysłem było by na dzień dobry wydzielić logikę, od ustawiania pozycji okien do osobnej klasy. Wiec gdy pojawi się pomysł zapisywania pozycji itp, miałbyś już dobry punkt wyjścia.

Warto zauważyć ze większość okienek ma 2 lub 3 hierarchie okienek. Główne, pomocnicze i normalne. Np. visual ma files, tools, i czasem normalne dialogi.
Ty będziesz musiał utrzymywać 2 stany, ostatnio używany tool lub okno główne, oraz ostatnio używane okno główne. Wszystko z eventami, przed po w trakcie. Zgranie tego ładnie z focusem WPF, jest nie trywialne, ale nie ma tragedii.

Wysoko poziomowo nie potrzebujesz dużo więcej, ew. jakiś interfejs na okno żeby dało rade nimi sterować wysokość szerokość styl.

Implantacje formy zrobiłbym tak:

0 czytasz jak działają eventy drag-drop i jak przekazywać dane, do wygooglowania
0.1 Przeczytaj jak działają viewModele, i jak bindować dane. Wystarczy Ci najprostsza wersja.
0.2 Znajdz najprostsza możliwą wersje InotifyProertyChanged i napisz 'code snippset' na tworzenie propsów, wywołujących ten event.

1 - Piszesz kontrolkę która przypomina tab-control, ze scrolami, z możliwością ustawiania listy tabów lewo-prawo-góra,-dół, przesuwania ich lewo prawo i co Ci sie tam podoba, oraz z możliwością dodawania kontrolek. które wyświetlana się w środku. Przydatny pewnie będzie event tabDrabbed albo cos takiego. To ma być taki koń roboczy dla Twojej appki.

2 - piszesz kontrolkę która ma 5(czasem wiecej) pojawiających się kwadracików gdy dragujesz nad nia właściwe dane*. Na drop : jeśli nie ma tam nic jeszcze dodajesz kontrolkę 1), i sterujesz jej wyglądem, jeśli jest dodajesz kolejnego taba do niej. Implementacja to proscizna, kilka kwadracików(tez możesz jako kontrolki napisać) oraz grid ze spliterami(to do rozciągania). Jeśli nic nie ma w danym celu dajesz romiar na 0 i widok na collapsed. To koń roboczy numer 2.

  • Prościej może być ustawić stan, `przerzucam okno ABC'

3 - Piszesz kontrolkę reprezentującą okienko dokowane, z pinem, eventami na odpinanie, zamykanie, ciagniecie za tytuł, zawiara w sobie i steruje kontrolką nr 2

4 - piszesz kontrolkę i logike do reprezentacji okienka(NIE OKIENKO), minimalizacją, przesuwaniem itp. rozmiarem itp. itd. zawiera w sobie i steruje kontrolką nr 2

5 - Piszesz kontrolkę która będzie siedzieć w twoim main-window, miedzy ribbonem, a status barem. Zawierać będzie w sobie kontrolkę nr.1 jako taki punkt startowy. to jest miejsce gdzie możesz dodać wsparcie dla alt+tab, szukajek itp.

Komunikacje miedzy kontrolkami, mozna napisać na kilka sposobów, ale zanim to bardzo ważna uwaga, 1,2,3,4, i pewnie 5, to nie jest publiczne API. Nie bawisz się wzorce, projektowe, rzeźbienie w XAML'u. nie trywialne bindingi danych, wyrafinowane struktury danych. Nie mówię ze masz robic lipe. To że zamiast pisać jednego wielkiego bloba masz 5 kontroleczek jednego przeznaczenia, daje Ci fajne możliwości. W code behind piszesz kod, odpowiedzialny za pozycjonowanie elementów, dodawnie odejmowanie kontrolek, ale tylko tego aspektu wizualnego lub frameworkowego. Jak musisz coś przesunąć o 5px, przesuwasz, podpinasz event handlary i delegujesz je dalej, ale nie robisz zadnej logiki stricte.

Przy takim podejściu uzyskamy wszystkie cegiełki które są potrzebne, żeby poskładać nasz system okienkowy. Zostaje problem skomunikowania tego wszystkiego razem.
Ogólnie widzę dwie opcje:
A) eventami przerzucasz informacje na najwyższy poziom, tj. nr 6. tam wszystko ogarniasz, a kontrolkami niżej sterujesz korzystając z referecji do nich. Zaletą jest to zę to najprostsze podejście które pozwoli uniknąć rozrzucenia, logiki i haków wszędzie i byle jak. Wadą jest to zę możesz skończyć z 1000 liniami sterującymi wszystkim naraz, ale nie musisz.
B) Możesz napisać view modele. Głowna kontrolka miała by swój viewModel, a każde dziecko, dostawało by dedykowany dla siebie przy tworzeniu. Kontrolki do view modelu przekazywały by informacje, zaczęto przesuwać, kliknięto na tab. A view model, przekazywał by te informacje, do modelu czyli tego singletna od którego zaczynaliśmy, oraz sterował kontrolkami, np. wysmażając nie aktywne okna lub przenosząc controlki z zadokowanego okna do okna pływającego.
I w drugą stronę, gdy w modelu, ktoś wywoła aktywuj mi okno, view model przestawi widok jak trzeba.

Jako model przekazujesz faktyczną implementacje, singletona od okienek lub wewnętrzy interfejs który pozwala na więcej.

Jak wszystko pójdzie sprawnie dostaniesz, UI w którym możesz wysterować absolutnie wszystkim, co do pixela, ViewModele z grupują logikę w jednym miejscu, pozwolą troche reuzyć kod i ochronią Cię przed tygodniami debugowania scenariuszy typu: jak ustawiam to w UI to leci taki event, na co reaguje tak i tak, co wywołuje kolejny event.. (wystarczy dać flagę, ze to rozróżniającą input od usera i ten wywołany z kodu). A publiczny interface będzie ładnie z enkapsulowany interfejsem.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.