Dziedziczenie a UserControl WPF - Jest to niemożliwe?

Dziedziczenie a UserControl WPF - Jest to niemożliwe?
gswidwa
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 lat
  • Postów:839
0

Witajcie :)
Próbuję stworzyć kalse bazową dla dwoich kilku kontrolek użytkownika, ponieważ będą one posiadały wiele tych samych cech. Przykład:

Kopiuj
public partial class CreateAccountPanel : KlasaBazowa
    {
        public CreateAccountPanel()
        {
            InitializeComponent();
           
        }
}
Kopiuj
public abstract class KlasaBazowa : UserControl
    {

    }

Problem pojawia się, kiedy próbuję skorzystać z klasy Dispatcher lub ustawić DependencyProperty. Po chwili ooleowania okazuje się, że np. Dispatcher jest klasą o modyfikatorze "public sealed", czyli nie może być klasą bazową. Czyli rozumiem, że kontrolki nie mogą dziedziczyć niczego poza UserControl, ponieważ w C# można dziedziczyć tylko jedną klasę?

grzesiek51114
grzesiek51114
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:2442
0

W C# można dziedziczyć tylko od jednej klasy, pod warunkiem, że nie jest sealed lub od wielu interfejsów. Nie można dziedziczyć od struktur, które z definicji są sealed.

Czyli rozumiem, że kontrolki nie mogą dziedziczyć niczego poza UserControl, ponieważ w C# można dziedziczyć tylko jedną klasę?

Można to obejść, bo zawsze możesz zrobić klasę, która dziedziczy od UserControl (i w niej implementować różne, interesujące Cię ficzery), a po której będą dziedziczyć Twoje inne klasy.

edytowany 2x, ostatnio: grzesiek51114
gswidwa
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 lat
  • Postów:839
0

Tak, ale według

Kopiuj
public sealed class Dispatcher

nie będę wtedy mógł go użyć wewnątrz CreateAccountPanel

edytowany 1x, ostatnio: gswidwa
grzesiek51114
grzesiek51114
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:2442
0

Jeżeli klasa jest sealed to zapomnij o dziedziczeniu po niej, tak jak napisałem.
Zastanów się czy aby zamiast dziedziczenia nie użyć po prostu kompozycji.

edytowany 1x, ostatnio: grzesiek51114
gswidwa
jak możesz mi to robić :c
grzesiek51114
grzesiek51114
to kompozycję zrób zamiast tego dziedziczenia.
gswidwa
Pierwsze słyszę, ale już znalazłem artykuł. Chyba to będzie to czego mi trzeba. Dziękuję :)
neves
  • Rejestracja:prawie 22 lata
  • Ostatnio:około 4 godziny
  • Lokalizacja:Kraków
  • Postów:1114
1

O ile dobrze pamiętam można budować takie hierarchie kontrolek w WPF:
CreateAccountPanel : KlasaBazowa
KlasaBazowa : UserControl

pod warunkiem że kontrolka która jest u samej podstawy nie ma dołączonej reprezentacji wizualnej w xamlu, czyli zamiast UserControl musiałbyś dziedzieczyć po ContentControl albo Control.

CreateAccountPanel : KlasaBazowa
KlasaBazowa : Control


edytowany 1x, ostatnio: neves
grzesiek51114
grzesiek51114
Nom, dokładnie to chciałem zasugerować autorowi; żeby zrobić drzewko dziedziczenia. Tylko doprawdy nie wiem do czego ten Dispatcher. :-)
neves
też nie mam pojęcia o co chodzi z tym dispatcherem i po co po nim dziedziczyć :O
gswidwa
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 lat
  • Postów:839
0

Tak to mniej więcej wygląda.
screenshot-20180801234854.png

  1. ModuleCollection to klasa zawierająca wszystkie obiekty ModuleElement, które służą do podstawowej obsługi modułów, czyli otwieranie, zamykanie, przesyłanie zdarzeń oraz komuniakcję między
    modułami.

  2. ModuleSelector to UserControl. Otrzymuje ona listę modułów z ModuleCollection i tworzy Buttony dzięki którym można otwierać/wybierać moduły.

  3. Module1, Module2 to UserControls. jest to graficzne przedstawienie całego modułu.

  4. ModuleViewer to UserControl. Służy on do wyświetlania Module1, Module2 itd. w zależności od tego, który aktualnie jest wybrany / otwarty. Otrzymuje on listę ModuleElement i przypisuje odpowiedni ModuleElement do odpowiedniej kontrolki

Interakcja między modułami wygląda następująco:
W kontrolce Module1 i Module2 mam stworzony obiekt ModuleElement, który reprezentuje jeden z obiektów ModuleElement z ModuleCollection.

  1. Załóżmy, że w module numer 2 wcisnąłem przycisk "uruchom moduł1".
  2. Wewnątrz każdego ModuleElement jest event, który przekazuje następujące argumenty:
Kopiuj
public Module_RequestActionEventArgs(eModule Source, eModule Target, eModuleRequest Question, object Data, bool RaiseEvent = true)
        {
            this.Source = Source;
            this.Target = Target;
            this.Question = Question;
            this.Data = Data;
        }
        public eModule Source { get; private set; }
        public eModule Target { get; private set; }
        public eModuleRequest Question { get; private set; }
        public object Data { get; private set; }
        public bool RaiseEvent { get; set; }
}

Każdy z tych Eventów we wszystkich ModuleElement jest obserwowany przez metodę w ModuleCollection, która w zależności od właściwości "target" wysyła całe zapytanie do odpowiedniego modułu. Ale zaraz zaraz - ModuleElement został został utworzony w innym wątku i nie mam do niego dostępu ;__;

screenshot-20180802000549.png

najlepsze jest to, że nawet użycie Dispatchera nie pomaga, dalej nie mam dostępu do wątku...

Problem rozwiązałem używając Dispatchera w innym miejscu, trochę nie po mojej myśli, bo zdarzenia nie miały mieć nic wspólnego z niczym poza ModuleElement no ale szkoda.
Eventy wysyłałem aż do MainWindow a potem on wysyłał je do ModuleCollector
screenshot-20180802002020.png

Kopiuj
private void hModuleViewer_ModuleRequest(object sender, AllTypes.ModulePanel.Events.Module_RequestActionEventArgs e)
        {
            e.RaiseEvent = false;
            switch (e.Question)
            {
                case eModuleRequest.Close:
                    Dispatcher.Invoke(() => Model.ModuleCollection.CloseModule(e.Target, e.Source, null));
                    break;
                case eModuleRequest.Open:
                    Dispatcher.Invoke(() => Model.ModuleCollection.OpenModule(e.Target, e.Source, e.Data));
                    break;
                case eModuleRequest.Reset:
                    Dispatcher.Invoke(() => Model.ModuleCollection.ResetModule(e.Target, e.Source, e.Data));
                    break;
                case eModuleRequest.Select:
                    Dispatcher.Invoke(() => Model.ModuleCollection.SelectModule(e.Target, e.Source, e.Data));
                    break;
                case eModuleRequest.SendData:
                    Dispatcher.Invoke(() => Model.ModuleCollection.SendModuleData(e.Target, e.Source, e.Data));
                    break;
                case eModuleRequest.Unselect:
                    Dispatcher.Invoke(() => Model.ModuleCollection.UnselectModule(e.Target, e.Source, e.Data));
                    break;
            }
        }
edytowany 1x, ostatnio: gswidwa

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.