Laden...

Kommentarfeld als Usercontrol oder CustomControl

Erstellt von Silver80 vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.465 Views
S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren
Kommentarfeld als Usercontrol oder CustomControl

Moin,

ich habe ein zwei Fragen bzgl. eines Steuerelements.

Ich möchte eine Steuerelement das in meiner Anwendung an mehereren Stellen (eigenständige Module) verwendet werden soll. Dieses Steuerelement soll aus nichts anderem bestehen wie eine Listbox ein Textfeld 2 Buttons (hinzufügen und löschen).

In der Textbox geben ich (klar was sonst 😉 ) einen Text ein. dann klicke ich auf den Button hinzufügen (Save) und der Text soll in die Liste aufgenommen werden (Und in der Db gespeichert werden).

Meine 1. Frage ist was verwende ich? Ein Usercontrol oder ein CustomControl. Zweite Frage: Benötige ich ein VM oder in diesem Fall nur Code behind da "nur" UserControl?

Am liebsten wäre es mir das Steuerelement als "geschlossen" anzusehen. Ich gebe eine Liste "rein" und bekomme eine Liste "raus"(Klar Bindung).

Das ganze soll als eine Arte Kommentarverfolgung anzusehen sein (Über mehere Module). Hat jemand damit Erfahrung gemacht ? Das Löschen und Speichern müsste auch von dem Element ausgelöst werden.

Ich hätte geren sowas auf die Art: Mehr soll nicht großartig passieren (siehe Anhang)

MainWindow

<Grid>
   <Comment:CommentControl  MyComments="{Binding Path=Comments}" />
</Grid>
709 Beiträge seit 2008
vor 5 Jahren

Guten Morgen Silver80,
ich würde dafür ein UserControl verwenden, da es damit in meinen Augen einfacher umzusetzen ist.
Die Eigenschaften, die du binden willst, müsstest du dann als DependencyProperties im CodeBehind anlegen.
Für das Anstoßen des Lade-/Speichervorgangs hättest du mehrere Möglichkeiten.
Zum Einen könntest du entsprechende Events anbieten, die dann z.B. das Aktualisieren der ItemsSource anstoßen oder sagen, dass ein neuer Kommentar hinzugefügt wurde, der nun gespeichert werden muss. Du könntest aber auch ein Interface bereitstellen (z.B. ICommentManager oder so), von dem du eine Implementierung als Objekt in einer der DependencyProperties erwartest.

4.931 Beiträge seit 2008
vor 5 Jahren

Hallo,

für deinen Anwendungsfall würde ich ein UserControl nehmen, da du bestehende Controls zusammen verwendest, s.a. The differences between CustomControls and UserControls.

Und zum von pinki angesprochenen Thema gibt es auch einen zugehörigen Artikel: DependencyProperties

2.078 Beiträge seit 2012
vor 5 Jahren

Ich schließe mich meinen Vorrednern an, ein UserControl wäre mein Mittel der Wahl.

Allerdings würde ich auch ein ViewModel dazu verwenden. Du hast schon am Anfang eine konkrete Nicht-View-Funktion (das Speichern) und wenn noch mehr dazu kommt (Ein Kommentar melden, ein Admin kann löschen, etc.), wirst Du über ein ViewModel sehr froh sein. Außerdem brauchst Du dann keine DependencyProperties mehr.

Alternativ kannst Du natürlich für jede Funktion eine DependencyProperty erstellen. Diese Command-Property kann an jedes x-beliebigen ViewModel gebunden werden und wird aus der View bei jeder Funktion aufgerufen. Dazu dann noch weitere Properties für z.B. die Liste.
Der Vorteil ist, dass die View an kein konkretes ViewModel gebunden ist, allerdings ist es auch mehr Aufwand und wahrscheinlich wird es sowieso immer das gleiche ViewModel sein.

S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren

Vielen Dank... dann passt das soweit...

Merci

S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren

So ich hätte dann doch noch eine Frage.... Ich komme leider nicht weiter.

Ich habe ein Hauptfenster in dem das UserControl nun gesetzt ist.

// Im MainWindow

<Grid>
   <Comment:CommentControl  Id="{Binding Path=SelectedObject.ID}" />
</Grid>

Das MainWindow hat sein eigenes ViewModel als auch das UserControl. Nun ich will wenn ich ein Objekt aus dem MainWindow im VM auswähle eine ID an das UserControl übergeben... Um genau zu sein an dessen VM.

Wie sendet (übergibt eine [int] ID) das VM des MainWindows das VM des Usercontrols...

Brauche ich da eine DependencyProperty im xaml.cs des Usercontrols ? Ist das der richtige weg ? Wie komme ich dann vom xaml.cs in das VM ?

Das wäre der aktuelle Stand... wirkt aber für mich nicht 100% sauber.

  

    public partial class CommentControl : UserControl
    {
        static CommentUserControlViewModel VM;
        public CommentControl()
        {
            InitializeComponent();

            VM = new CommentUserControlViewModel(DialogCoordinator.Instance);
            (this.Content as FrameworkElement).DataContext = VM;
        }
     
public static readonly DependencyProperty IdProperty = DependencyProperty.Register("Id", typeof(int), typeof(CommentControl), new FrameworkPropertyMetadata()
        {
            PropertyChangedCallback = OnDemoChanged,
            BindsTwoWayByDefault = true
        });

        public int Id
        {
            get { return (int)this.GetValue(IdProperty); }
            set { this.SetValue(IdProperty, value); }
        }

        private static void OnDemoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != e.NewValue)
            {
            // Wäre das richtig  ???
                VM.SetID((int)e.NewValue);
            }
        }

    }


Danke für eure Antworten

Silver

5.657 Beiträge seit 2006
vor 5 Jahren

Hi Silver80,

wie du die Schnittstelle gestaltest, bleibt letztendlich dir überlassen. Nur solltest du halt keine ID übergeben, wenn du eigentlich ein Objekt übergeben willst.

Besser wäre es sowieso, das Control nicht von der Implementierung der Anwendung und deren ViewModels abhängig zu machen. Ein Control will man ja in anderen Anwendungen wiederverwenden. Sonst könnte man auch einfach DataTemplates verwenden.

In deinem Fall kann man die Schnittstelle des Controls viel einfacher gestalten: Die vorhandenen Kommentare könntest du einfach als List<string> übergeben. Für die Benachrichtigung darüber, daß der Benutzer einen neuen Kommentar erstellt hat, würde sich hier ein Event CommentCreated oder so anbieten. Dann kann man das Control überall wiederverwenden, ohne daß zusätzliche Klassen benötigt werden.

Weeks of programming can save you hours of planning

S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren

Danke für deine Antwort Mrsparkle.

Ich sagte doch das ich es in mehreren modulen EINES Programms verwenden möchte. Deswegen ein Usercontrol. Das VM des UserControls brauche ich weil das UserControl das speichern und laden anhand dieser ID selbst übernhemen soll. (Rest-schnittstelle).

5.657 Beiträge seit 2006
vor 5 Jahren

Dann würde ich die Funktionalität im ViewModel kapseln, und die UI im dazugehörigen DataTemplate. Welchen Vorteil hat man sonst von dem UserControl?

Die Kommunikation mit einer Rest-Api gehört aber weder ins ViewModel, noch in ein UserControl.

Weeks of programming can save you hours of planning

S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren

Sorry (das meine ich nicht böse) aber das steht schon alles hier geschrieben. Mir fehlt das konstruktive.

5.657 Beiträge seit 2006
vor 5 Jahren

Welche Frage ist denn noch nicht beantwortet?

Weeks of programming can save you hours of planning

S
Silver80 Themenstarter:in
9 Beiträge seit 2017
vor 5 Jahren

Guten Morgen

MrSparkle.... Man kann

bool value = true;

if (value == true)
// oder
if(value)

schreiben.... Du wirst mir ja wohl recht geben das die erste if-Abfrage kein keinen Sinn macht und auch nicht gerade einem guten Stil entspricht.

Mein Konstrukt hier ist leider etwas anders als eine einfach If-Abfrage.

Ich will einfach nur wissen wie man (wenn man eine Komponente entwickelt, in diesem Fall ein UC das Kommentare "verwaltet", als eigenständiges UC entwickelt. - (Deswegen war die Überschrift auch UserControl oder CustomControl)). Ich kann das Ganze auch in einer eigenen Bibliothek entwickeln, wäre aber übertrieben da das alles nur in dieser Applikation benutzt wird. In mehreren Modulen. Ich will (weil es für mich am Sinnigsten ist, dass sich diese Komponente nur um das Kümmert was Sie soll. - Macht doch Sinn 😉 )

Angenommen ich brauche zukünftig keine Kommentare mehr - schmeiße ich das Ding einfach raus.

So und das alles kostet mich und Deine Zeit. Ich habe Beispiel-Code hinzugefügt (den ziemlich einfach gehalten) und wollte wissen - ist das ein sauberes Vorgehen? - Stimmt DAS was ich gemacht habe. (Static ViewModel ?). Es gibt bestimmt ein "sauberes" oder besser typisches Vorgehen.

Ich brauche keine Antworten in denen steht – „wie du das gestaltest bleibt die überlassen
-> siehe oben If-Abfrage - geht aber nicht schön / gut.
So lernt hier keiner was und es kostet nur Zeit das zu schreiben und zu lesen. Und wieder zu schreiben… (Ich hoffe Du siehst das als konstruktive Kritik – will ja kein Zorn heraufbeschwören 😉 )

Ach ja die REST-API wird nur vom VM aufgerufen 😉

Sorry

301 Beiträge seit 2009
vor 5 Jahren

Also ich bin jetzt nicht ganz sicher ob deine Frage noch offen ist oder nicht, aber ich kann ja einfach mal von meinen Erfahrungen zu deiner Frage was sagen.

Kurz ausgeholt:

In der Welt der Softwareentwicklung gibt es Meinungen in sehr großem Maße. Viele Ideen die sich in sehr kurzem Zeitraum entwickeln. Eine Meinung und Idee von vor 3 Wochen ist morgen schon wieder anders. Du kennst das vielleicht selbst. Den Code von vor 3 Monaten würdest du selbst nicht mehr so schreiben.

Ich denke das geht fast jedem so, auch Buchautoren, Speakern und Frameworkentwicklern. Ist ja auch klar wir entwickeln uns alle durch unsere Arbeit weiter.

Warum sage ich das? Ich habe das Gefühl du suchst nach einer allumfassenden richtigen Antwort die es nicht gibt. Du willst Erfahrungen und Meinungen hören die unterschiedlich sind. Es gibt einfache schnelle Lösungen und es gibt aufwändige "saubere" Lösungen. Was davon letztlich für dich wichtig ist können wir aber nicht beurteilen. Versuch dich ein wenig davon zu lösen, dass dein Code in 6 Monaten noch "toll" ist. Code ist wie reales Produkt mit einer gewissen Lebenszeit versehen.

Zu deinem Code:

1.) Ich würde ein UserControl verwenden. ViewModel als DataContext. UserControl selbst steuert nur UI Interaktion, ggf. mit Hilfe von Behaviors um spezielle Anforderungen umzusetzen.

2.) Das UserControl würde ich in eine Library packen sofern es von mehreren anderen Libraries verwendet wird. Ansonsten würde ich einen Namespace im selben Projekt erstellen.

3.) Das ViewModel hält für mich immer nur einen UI State. Es tut selber eigentlich nichts sondern delegiert lediglich aufrufe an ein Model.

4.) Mein Model gestalte ich möglich so, dass es mit UI NICHTS mehr zu tun hat und optimalerweise sogar in einer UI unabhängigen Library liegt. So lässt sich Businesscode leichter extrahieren.

5.) Static ViewModels würde ich persönlich nicht machen sondern vielmehr meiner Applikation ( diese ist ja bereits static ) einen ViewModelLocator ( muss kein DI Container sein ) geben der mir ViewModels bereitstellt. Ob dieser dann immer diesselbe Instanz gibt oder jedes Mal eine neue hängt von deinem Use Case ab ( z.B. soll beim Aufrufen der View alles so sein wie zuvor ).

Ich hoffe ich habe jetzt nicht völlig am Thema vorbei geredet.

Viel Erfolg weiterhin.

5.657 Beiträge seit 2006
vor 5 Jahren

Ich brauche keine Antworten in denen steht – „wie du das gestaltest bleibt die überlassen

Ich hab dir doch geschrieben, wie ich es umsetzen würde. Ein UserControl bzw. CustomControl ist für deine Anforderungen einfach zu viel Aufwand. Das geht wesentlich einfacher.

Wenn du alternative Vorschläge nicht hören willst, und dich dann noch darüber beschwerst - was erwartest du dir dann vom Forum?

Weeks of programming can save you hours of planning