Dziedziczenie a UserControl WPF - Jest to niemożliwe?

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:

public partial class CreateAccountPanel : KlasaBazowa
    {
        public CreateAccountPanel()
        {
            InitializeComponent();
           
        }
}
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ę?

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.

0

Tak, ale według

public sealed class Dispatcher

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

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.

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

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:
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

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;
            }
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1