C# WPF - MediaElement - Abspielen starten ohne CodeBehind

JetStre4m

Lieutenant
Registriert
Nov. 2007
Beiträge
578
Hallo zusammen,
Ich schreibe gerade einen kleinen Videoplayer in C#. Dazu nutze ich WPF, wobei sich selbstverständlich das "MediaElement" zur Darstellung des Videos eignet.
Ich möchte gerne in der gesamten Anwendung den "CodeBehind" leer lassen, also alles über eine eigene "ViewModel"-Klasse machen.

Leider habe ich dabei ein kleines Problem: Wie kann ich bei einem Klick auf einen Button das Abspielen in dem MediaElement starten? Dafür müsste ich nämlich normalerweise im CodeBehind die Play()-Methode des Elementes aufrufen, was ich jedoch verhindern will. Wie kann ich also in der ViewModel-Klasse die Methode eines View-Elementes aufrufen?

Ich hoffe, ich habe das Problem einigermaßen nachvollziehbar beschrieben :)
Mit Freundlichen Grüßen
JetSte4m
 
Es geht irgendwie, wenn man in WPF EventTrigger verwendet. Allerdings ist das so aufwendig bzw. mir zu aufwendig, mich da einzufuchsen. Lieber schreibe ich da eine Zeile C#-Code.

WPF beschreibt normalerweise nur das View, da jetzt noch einen Controller einzufügen, ist fast ein Ding der Unmöglichkeit. Dafür ist XAML eigentlich nicht ausgelegt und gedacht.
 
Hallo,
Da gibt es schon das tolle MVVM-Pattern und dann ist soetwas triviales nicht ohne beträchtlichen Mehraufwand sauber realisierbar? Schade...
 
Hi,

Da gibt es schon das tolle MVVM-Pattern und dann ist soetwas triviales nicht ohne beträchtlichen Mehraufwand sauber realisierbar? Schade...

Korrigiert mich, wenn ich mich irre: aber mit dem MVVM-Pattern ist eigentlich nichts ohne Mehraufwand machbar, oder sehe ich das so falsch? Gegenüber dem "klassichen" Code-Behind habe ich doch immer ein wenig "Von hinten durch die Brust ins Auge" oder nicht?

VG,
Mad
 
@JetStre4m
Du versuchst durch ein Event nur durch die Möglichkeiten des Views (sprich in XAML/WPF) ein anderes Event anzustoßen. Selbst beim MVVM ist das nicht möglich.
Das View ist rein für die Optik da. Events werden in erster Linie nur durchgeroutet. Aber auf Basis der Events irgendwelche Kommandos zu geben, das kann es mit Absicht nicht.
 
Da merkt man direkt das MVVM dem MVC Pattern unterlegen ist. Zwecks MediaElement gibt's aber vielleicht ne Lösung.

Und zwar hat das MediaElement ein LoadingBehavior. Wenn man Play nutzt muss dieses auf Manual gestellt werden, wenn man das nicht macht sollte beim DataBinding eigentlich direkt das Abspielen starten.
 
Naja, wenn das MediaElement ein xml-Attribut hätte (z.B. PlayMode) das man per Binding auf z.B. "Playing", "Paused" oder "Stopped" setzt, wäre das ohne Weiteres möglich - so viel Aufwand ist das nun auch wieder nicht.
Und ich benutze selbsterverständlich auch C#, nur nicht in der automatisch generierten Code-Behind Klasse, sondern in einer eigenen ViewModel Klasse.

Edit:
Ich habe tatsächlich einmal versucht, ein MediaElement mit eienem xaml-Property zu erstellen, welches den aktuellen "PlayMode" enthält und per Binding auf z.B. playing gesetzt werden kann.
Die neue MediaElement-Klasse sieht so aus:

Code:
public class CMediaElement : MediaElement
    {
        private string playMode = "stopped";
        public string PlayMode
        {
            get 
            {
                Console.WriteLine("GET");
                return (base.GetValue(PlayModeProperty) as string);
            }
            set 
            { 
                this.playMode=value;
                base.SetValue(PlayModeProperty, value);
                Console.WriteLine("2. "+value);
                if (value.Equals("playing"))
                {
                    this.Play();
                }
            }
        }
        public static DependencyProperty PlayModeProperty =
          DependencyProperty.Register("PlayMode", typeof(string), typeof(CMediaElement));
    }

Die View-Model Klasse enthält das Property "PlayState":
Code:
 private string playState;
        public string PlayState
        { 
            get
            {
                return playState;
            }
            set
            {
                this.playState=value;
                if(PropertyChanged!=null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("PlayState"));
                }
            }
        }

..Welches in XAML an das entsprechenden PlayMode-Property des neuen Media-Elementes gebunden ist:
Code:
<local:CMediaElement LoadedBehavior="Manual" Grid.Row="0" PlayMode="{Binding PlayState}" x:Name="me_player" Source="{Binding PlayerSource}" />

Wenn ich nun bei einem Klick auf den Button die PlayState-Eigenschaft in der ViewModel-Klasse ändere, wird dort der setter aufgerufen, allerdings nicht in der PlayMode-Eigenschaft der CMediaElement-Klasse.

Es scheint also, als ob das CMediaElement garnicht mitbekommt, dass sein PlayMode Property geändert wurde.
Wenn ich die Source-Eigenschaft nach einem Buttonclick per Binding ändere, funktioniert das Ganze...
Um das Ganze noch einmal zu konkretisieren, wie sage ich der PlayMode Eigenschaft in CMediaElement, dass es geändert wurde, wenn ich die PlayState-Eigenschaft in der ViewModel-Klasse ändere?
Denn das Binding scheint das nicht wie erwartet automatisch zu lösen...
Seltsame Sache, bestimmt habe ich irgendetwas vergessen :D
 
Zuletzt bearbeitet:
...in diesem Szenario. Für WPF ist ansonsten MVC das weniger geeignete Pattern.
Und Warum?

@JetStre4m
Warum probierst du nicht das LoadingBehavior aus? Dann brauchst du auch kein eigenes UserControl.
 
Das habe ich schon, es funktioniert auch, aber die Möglichkeiten des standard MediaElements sind zu eingeschränkt. Sachen wie Pausieren, Springen, Lautstärke ändern usw. gehen über xaml nicht mehr, sind aber theoretisch relativ leicht nachzurüsten. Die Frage ist nur warum mein Lösungsversuch nicht funktioniert...
 
@JetStre4am:
Mal ne kleineFrage, zählt das für dich auch als CodeBehind? :p (falls das so überhaupt in deine Klasse passt).
Code:
<MediaElement LoadedBehavior="Manual" Source="blabla" Name="mediaElement1" />
<Button Content="Button" Name="button1" Click="button1_Clicked" />
<x:Code><![CDATA[
   void button1_Clicked(object sender, EventArgs E)
   {
      mediaElement1.Play();
   }
]]></x:Code>
 
Hi, ob das jetzt per Definition als CodeBehind zählt weiß ich nicht, allerdings sprengt es vorbildhaft die angestrebte strikte Trennung zwischen Code und Design :). Ich habe mir auch mittlerweile sagen lassen, dass das MVVM-Pattern es nicht per se verbietet im CodeBehind etwas stehen zu haben - von daher ist mein Problem im Grunde gelöst...
 
Zurück
Oben