Вернуть предыдущему родителю UIElement

249
05 августа 2017, 02:02

Необходимо выдернуть UIElement из контейнера, на время, после вернуть его обратно, нужен самый быстрый и рабочий способ.

Ранее делал так:

  1. В метод передаю ссылку на предыдущий родитель.
  2. Открепляю UIElement от родителя, зная его тип.
  3. Провожу необходимые манипуляции "в моем случае передаю его на новое окно".
  4. Открепляю UIElement от окна, возвращаю его на место предыдущему родителю зная его тип.

В данном методе, есть множество недостатков, установить родителя можно быстро, но в режиме дебага, весь стек вывода закидывается исключениями, т.к. UIElement не успевает отсоединиться от установленного мною нового родителя, и в цикле пытаюсь его вернуть обратно.

В принципе это работает, но медленно, и не совсем так как мне необходимо. Т.к. контейнер может быть любым, а его тип узнать можно, но это снова не то что мне нужно.

Вот класс UIElement'a который необходимо переносить из одного контейнера в другое окно:

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Yume.Controls.Extensions;
using Yume.Controls.Input;
using MediaElementBase = System.Windows.Controls.MediaElement;
namespace Yume.Controls
{
    #region Parts Template
    [TemplatePart(Type = typeof(MediaElementBase), Name = PART_MediaElementBase)]
    [TemplatePart(Type = typeof(ContentPresenter), Name = PART_ControlPlayerContainer)]
    #endregion
    public class MediaElement : Control
    {
        #region Constructors
        public MediaElement()
        {
            IsInDesignMode = GetValue<bool>(DesignerProperties.IsInDesignModeProperty);
        }
        static MediaElement()
        {
            var style = CreateDefaultStyles();
            StyleProperty.OverrideMetadata(typeof(MediaElement), new FrameworkPropertyMetadata(style));
        }
        #endregion
        #region Enevts
        public event StateChengeded StateChanged;
        public delegate void StateChengeded(object sender, MediaStateChangedEventArgs args);
        #endregion
        #region DependencyProperty
        // Using a DependencyProperty as the backing store for SetFullScreenCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SetFullScreenCommandProperty =
            DependencyProperty.Register("SetFullScreenCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for RemoveFullScreenCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RemoveFullScreenCommandProperty =
            DependencyProperty.Register("RemoveFullScreenCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for StopCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StopCommandProperty =
            DependencyProperty.Register("StopCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for CloseCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CloseCommandProperty =
            DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for PauseCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PauseCommandProperty =
            DependencyProperty.Register("PauseCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for PlayCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlayCommandProperty =
            DependencyProperty.Register("PlayCommand", typeof(ICommand), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for PreviewImage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PreviewImageProperty =
            DependencyProperty.Register("PreviewImage", typeof(BitmapImage), typeof(MediaElement),
                new PropertyMetadata(null));
        // Using a DependencyProperty as the backing store for MediaState.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MediaStateProperty =
            DependencyProperty.Register("MediaState", typeof(MediaElementStates), typeof(MediaElement),
                new PropertyMetadata(MediaElementStates.Stop));
        // Using a DependencyProperty as the backing store for IsInDesignMode.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsInDesignModeProperty =
            DependencyProperty.Register("IsInDesignMode", typeof(bool), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for ShowPlayerControls.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ShowPlayerControlsProperty =
            DependencyProperty.Register("ShowPlayerControls", typeof(bool), typeof(MediaElement),
                new PropertyMetadata(null));
        // Using a DependencyProperty as the backing store for PlayerControlPosition.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlayerControlPositionProperty =
            DependencyProperty.Register("PlayerControlPosition", typeof(PlayerControlPosition), typeof(MediaElement),
                new PropertyMetadata(PlayerControlPosition.Bottom));
        // Using a DependencyProperty as the backing store for PlayerControl.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlayerControlProperty =
            DependencyProperty.Register("PlayerControl", typeof(object), typeof(MediaElement));
        // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(Uri), typeof(MediaElement));
        #endregion
        #region Props
        public BitmapImage PreviewImage
        {
            get => GetValue<BitmapImage>(PreviewImageProperty);
            set => SetValue(PreviewImageProperty, value);
        }

        public MediaElementStates MediaState
        {
            get => GetValue<MediaElementStates>(MediaStateProperty);
            set => SetValue(MediaStateProperty, value);
        }
        public bool IsInDesignMode
        {
            get => GetValue<bool>(IsInDesignModeProperty);
            set => SetValue(IsInDesignModeProperty, value);
        }
        public bool ShowPlayerControls
        {
            get => GetValue<bool>(ShowPlayerControlsProperty);
            set => SetValue(ShowPlayerControlsProperty, value);
        }
        public PlayerControlPosition PlayerControlPosition
        {
            get => GetValue<PlayerControlPosition>(PlayerControlPositionProperty);
            set => SetValue(PlayerControlPositionProperty, value);
        }
        public object PlayerControl
        {
            get => GetValue<object>(PlayerControlProperty);
            set => SetValue(PlayerControlProperty, value);
        }
        public Uri Source
        {
            get => GetValue<Uri>(SourceProperty);
            set => SetValue(SourceProperty, value);
        }
        #endregion
        #region Methods
        protected virtual void OnStateChanged(object sender, MediaStateChangedEventArgs args)
        {
            StateChanged?.Invoke(sender, args);
            MediaState = args.CurrentState;
        }
        protected virtual void OnStateChanged(object sender, MediaStateChangedEventArgs args, Action doAction)
        {
            OnStateChanged(sender, args);
            doAction?.Invoke();
        }
        private T GetValue<T>(DependencyProperty dp)
        {
            return (T) GetValue(dp);
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _baseMediaElement = _baseMediaElement ?? GetTemplateChild<MediaElementBase>(PART_MediaElementBase);
            _playerControlPresenter = _playerControlPresenter ??
                                      GetTemplateChild<ContentPresenter>(PART_ControlPlayerContainer);
            PlayCommand = new RelayCommand(o => Play(),
                o => MediaState == MediaElementStates.Pause ||
                     MediaState == MediaElementStates.Stop && Source != null);
            PauseCommand = new RelayCommand(o => Pause(), o => MediaState == MediaElementStates.Play && Source != null);
            StopCommand = new RelayCommand(o => Stop(),
                o => MediaState == MediaElementStates.Pause || MediaState == MediaElementStates.Play ||
                     MediaState != MediaElementStates.Stop && Source != null && (_baseMediaElement.HasVideo ||
                                                                                 _baseMediaElement.HasAudio));
            CloseCommand = new RelayCommand(o => Close(),
                o => Source != null && _baseMediaElement.HasVideo || _baseMediaElement.HasAudio);
            SetFullScreenCommand = new RelayCommand(o => this.SetFullScreen());
            RemoveFullScreenCommand = new RelayCommand(o => this.RemoveFullScreen());
        }
        private T GetTemplateChild<T>(string templateName) where T : class
        {
            return GetTemplateChild(templateName) as T;
        }
        private static Style CreateDefaultStyles()
        {
            var style = new Style(typeof(MediaElement), null);
            style.Setters.Add(new Setter(FlowDirectionProperty, FlowDirection.LeftToRight));
            style.Seal();
            return style;
        }
        public void Play()
        {
            OnStateChanged(this, new MediaStateChangedEventArgs(MediaElementStates.Play),
                () => _baseMediaElement?.Play());
        }
        public void Pause()
        {
            OnStateChanged(this, new MediaStateChangedEventArgs(MediaElementStates.Pause),
                () => _baseMediaElement?.Pause());
        }
        public void Stop()
        {
            OnStateChanged(this, new MediaStateChangedEventArgs(MediaElementStates.Stop),
                () => _baseMediaElement?.Stop());
        }
        public void Close()
        {
            OnStateChanged(this, new MediaStateChangedEventArgs(MediaElementStates.Stop),
                () => _baseMediaElement?.Close());
        }
        #endregion
        #region TemplatePart Names
        // ReSharper disable InconsistentNaming
        private const string PART_MediaElementBase = "PART_MediaElementBase";
        private const string PART_ControlPlayerContainer = "PART_ControlPlayerContainer";
        // ReSharper restore InconsistentNaming
        #endregion
        #region TemplatePart Objects
        private MediaElementBase _baseMediaElement;
        private ContentPresenter _playerControlPresenter;
        #endregion
        #region MediaElement Commands
        public ICommand PlayCommand
        {
            get => GetValue<ICommand>(PlayCommandProperty);
            set => SetValue(PlayCommandProperty, value);
        }

        public ICommand PauseCommand
        {
            get => GetValue<ICommand>(PauseCommandProperty);
            set => SetValue(PauseCommandProperty, value);
        }

        public ICommand StopCommand
        {
            get => GetValue<ICommand>(StopCommandProperty);
            set => SetValue(StopCommandProperty, value);
        }
        public ICommand CloseCommand
        {
            get => GetValue<ICommand>(CloseCommandProperty);
            set => SetValue(CloseCommandProperty, value);
        }

        public ICommand SetFullScreenCommand
        {
            get => GetValue<ICommand>(SetFullScreenCommandProperty);
            set => SetValue(SetFullScreenCommandProperty, value);
        }

        public ICommand RemoveFullScreenCommand
        {
            get => GetValue<ICommand>(RemoveFullScreenCommandProperty);
            set => SetValue(RemoveFullScreenCommandProperty, value);
        }

        #endregion
    }
}

Расширяющий класс:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
// ReSharper disable SuggestVarOrType_SimpleTypes
namespace Yume.Controls.Extensions
{
    public static class MediaElementExtensions
    {
        private static object _previewParentContainer;
        public static Window SetFullScreen(this MediaElement mediaElement)
        {
            throw new NotImplementedException();
        }
        public static void RemoveFullScreen(this MediaElement mediaElement)
        {
            throw new NotImplementedException();
        }
    }
}
Answer 1

По моему мнению, лучшим решением может стать использование класса MediaPlayer с реализацией собственной отрисовки видео, использования класса VideoDrawing а так же перегруженный конструктор контрола, который в случае инициализации с применением класса MediaPlayer будет использовать переданный объект для отрисовки. В противном случае будет инициализировать новый экземпляр данного класса, и использовать его.

Но я все еще жду каких либо предложений.

READ ALSO
Изогнутый Progress Bar c# WPF

Изогнутый Progress Bar c# WPF

Ребят, подскажите как сделать полукруглый прогресс бар? С обычным вообще не возникает проблемНаходил только больно уж сложные, круглые примеры

461
Как создать правильно бизнес модель в devexpress xaf?

Как создать правильно бизнес модель в devexpress xaf?

Добрый день У меня возникла проблема, так как в использовании данного фреймворка я новичокЯ хотел создать самый простой и обычный task manager

286
C# &mdash; поиск элемента со значением value

C# — поиск элемента со значением value

Есть код, написанный на PhantomJS driver:

397
Зачем усложнять жизнь&hellip; Converter в Binding

Зачем усложнять жизнь… Converter в Binding

Здравствуйте, скажите пожалуйста зачем и в чём удобства Converter'а в Binding'е?

250