c# - Switching a Control over different windows inside ContentControl -
i making video player. in application have total screen window , normal window.
i using contentcontrol bind mediaelement within it, viewmodel. instance of mediaelement created within viewmodel easier command control via code.
now have button show window contentcontrol can assigned same mediaelement. works. element switch normal window fullscreen.
problem when close total screen window not switch back, normal window contentcontrol.
i tried rebinding control, works command seen within command control not appear work, of commands.
fullscreenview
<grid> <contentcontrol content="{binding playerbaseviewmodel.mediacontrol, mode=oneway}" /> </grid> playerbaseview
<grid> <contentcontrol content="{binding mediacontrol}" /> </grid> call fullscreen
internal void showfullscreen(playerbaseviewmodel playerbaseviewmodel) { var fullscreenview = new fullscreenview(); var fullscreenviewmodel = new fullscreenviewmodel( playerbaseviewmodel, this.playcontrolviewmodel, this.source); fullscreenview.datacontext = fullscreenviewmodel; fullscreenview.showdialog(); fullscreenviewmodel.dispose(); } base
public frameworkelement mediacontrol { { homecoming this.mediacontrol; } set { this.mediacontrol = value; if (this.mediacontrol != null) { this.mediacontrol.horizontalalignment = horizontalalignment.center; } this.raisepropertychanged(() => this.mediacontrol); } } private void fullscreen() { if (this.showfullscreen != null) { messagehelper.showmessage( string.format(staticdata.messageplayerbaseviewmodelfullscreen, this.device.name), string.format(staticdata.messageplayerbaseviewmodelfullscreendetails, this.device.name), 3); var command = this.mediacontrol; this.showfullscreen(this); this.mediacontrol = null; control.datacontext = this; this.mediacontrol = control; this.device.resetalldevice(); } } playeraudiovideoviewmodel
public class playeraudiovideoviewmodel : playerbaseviewmodel { #region static fields private static readonly stopwatch watch = stopwatch.startnew(); #endregion #region fields private readonly dependencypropertydescriptor mediapositiondependencypropertydescriptor = dependencypropertydescriptor.fromproperty(mediaseekingelement.mediapositionproperty, typeof(uielement)); private readonly dispatchertimer timer = new dispatchertimer(dispatcherpriority.render); private mediaelement mediaelement = new mediaelement(); #endregion #region constructors , destructors public playeraudiovideoviewmodel(devicemodel devicemodel) : base(devicemodel) { this.mediacontrol = this.mediaelement; this.mediaelement.begininit(); this.timer.interval = timespan.frommilliseconds(200); this.timer.tick += this.timertick; this.mediaelement.loadedbehavior = mediastate.manual; this.mediaelement.scrubbingenabled = true; this.mediaelement.mediaopened += this.mediaopened; this.mediaelement.mediaended += this.mediaended; this.mediapositiondependencypropertydescriptor.addvaluechanged(this.mediaelement, this.positionchanged); this.mediaelement.endinit(); } #endregion #region public methods , operators public override void cleanup() { this.mediacontrol = null; this.mediaelement.source = null; this.mediaelement.mediaopened -= this.mediaopened; this.mediaelement.mediaended -= this.mediaended; this.mediaelement.loadedbehavior = mediastate.manual; this.mediaelement.unloadedbehavior = mediastate.manual; this.timer.tick -= this.timertick; this.mediaelement.source = null; this.mediaelement = null; } public override void loaddata() { if (this.data != null) { var cont = (contentmoving)this.data.content; if (this.mediaelement.source == null || !this.mediaelement.source.localpath.equals(cont.path.fullname)) { this.mediaelement.source = new uri(cont.path.fullname, urikind.absolute); this.mediaelement.pause(); } else { this.mediaelement.position = cont.position.subtract(new timespan(0, 0, 0, 0, cont.position.milliseconds)); // this.changeplayspeed(); this.timer.start(); } } else { this.mediaelement.source = null; } debug.print("d {0} load.", this.devicename); } public override void muteaudio(bool mute) { this.mediaelement.ismuted = mute; } public override void pause() { debug.print("d {0} pause.", this.devicename); this.mediaelement.pause(); } public override void play() { debug.print("d {0} play.", this.devicename); this.mediaelement.play(); } #endregion #region methods private void mediaended(object sender, routedeventargs e) { if (this.mediaelement.position == this.mediaelement.naturalduration) { this.dataendreached(); } } private void mediaopened(object sender, routedeventargs e) { if (this.data != null) { var cont = (contentmoving)this.data.content; if (this.device.status == playstatus.play) { this.device.resetalldevice(); } else { this.mediaelement.position = cont.position.subtract(new timespan(0, 0, 0, 0, cont.position.milliseconds)); this.changeplayspeed(); } } this.dataloaded(); } #endregion } }
the reason why original window losing video because when closing total screen window; mediaelement unloading part of window's ui tree. prepare need first alter mediaelement loading/unloading behavior manual. default in automatic mode. why media starts playing right after source loaded. means when unloaded event fires ui tree, mediaelement close.
once set behavior manual, still need handle total screen window closing event, can rebind contentcontrol.content (mediaelement) in main window. trigger "loaded" event in mediaelement again, allow mediaelement go on playback in main window.
here sample code; straight forward. showing viewmodel constructor , relevant methods.
parts of viewmodel.cs:
public relaycommand maximize { get; set; } public relaycommand play { get; set; } private mediaelement media; // bound media property notification public mediaelement media { { homecoming this.media; } set { this.media = value; // modify next line needed // custom property changed handler this.changed("media"); } } // constructor, setup command, media element etc. public viewmodel() { // 2 button commands this.maximize = new relaycommand(this.executemaximizecommand); this.play = new relaycommand(this.executeplaycommand); // media element this.media = new mediaelement(); // need set loaded , unloaded behavior manual // means video won't play right-away after loading // have phone call .play() method start playback // add together play button if don't have 1 , bind play command this.media.loadedbehavior = mediastate.manual; this.media.unloadedbehavior = mediastate.manual; // next example. doesn't need here this.media.source = new uri("test.mp4", urikind.relative); } public void executemaximizecommand() { var fullscreen = new fullscreen(); // need handle closing event // can trigger playback // go on in smaller window fullscreen.closing += fullscreen_closing; fullscreen.datacontext = this; fullscreen.showdialog(); } public void executeplaycommand() { this.media.play(); } // event handler fullscreen window closing void fullscreen_closing(object sender, canceleventargs e) { // trigger property alter notification // forcing null , original value // trigger binding kick-in 1 time again // redraw mediaelement ui , go on // playback var temp = this.media; this.media = null; this.media = temp; } mainwindow.xaml
<window x:class="wpfapplication1.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <grid> <grid.rowdefinitions> <rowdefinition height="*" /> <rowdefinition height="30" /> </grid.rowdefinitions> <contentcontrol content="{binding media}" /> <stackpanel grid.row="1" orientation="horizontal"> <button command="{binding maximize}" content="maximize" margin="2" /> <button command="{binding play}" content="play" margin="2" /> </stackpanel> </grid> </window> mainwindow.cs
public mainwindow() { initializecomponent(); this.datacontext = new viewmodel(); } fullscreen.xaml
<window x:class="wpfapplication1.fullscreen" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="fullscreen" height="300" width="300" windowstate="maximized"> <grid> <contentcontrol x:name="mediacontentcontrol" content="{binding path=media}"> </contentcontrol> </grid> </window> c# wpf xaml contentcontrol
No comments:
Post a Comment