c# - WPF 应用程序中的条件设置

标签 c# wpf binding settings

我正在为我的媒体播放器设置用户可更改的设置,我正在努力寻找解决问题的优雅方法。

例如,我的一个设置 - 在最后一帧暂停视频,如果未选中,它将继续播放列表,或者如果只有一个文件,重置它并在开始时暂停。

我是这样实现的:

private void OnMediaEndedCommand()
{
    if (GeneralSettings.PauseOnLastFrame)
    {
        MediaPlayer.SetMediaState(MediaPlayerStates.Pause);
        return;
    }
    if (PlayListViewModel.FilesCollection.Last().Equals(PlayListViewModel.FilesCollection.Current) && !Repeat)
    {
        ChangeMediaPlayerSource(PlayListViewModel.ChangeCurrent(() => PlayListViewModel.FilesCollection.MoveNext()));
        MediaPlayer.SetMediaState(MediaPlayerStates.Stop);
        return;
    }
    ChangeMediaPlayerSource(PlayListViewModel.ChangeCurrent(() => PlayListViewModel.FilesCollection.MoveNext()));
}

这包含在主窗口的 ViewModel 中,其中媒体元素是 GeneralSettings.PauseOnLastFrame 是一个 bool 属性。

此命令绑定(bind)如下:

<MediaElement ....>
    <ia:Interaction.Triggers>
        <ia:EventTrigger EventName="MediaEnded">
            <ia:InvokeCommandAction Command="{Binding MediaEndedCommand}"/>
        </ia:EventTrigger>
    </ia:Interaction.Triggers>
</MediaElement>

它有效但很糟糕,我应该如何以优雅的方式实现这样的设置系统?一些设置可能不是 bool 值,它们可能有多个选项,一些可能仅在启动时应用,而另一些,如上图所示,基于事件。

最佳答案

根据您提供的信息和示例代码,我建议

方法 - 1

ViewModel 与 System.Configuration.ApplicationSettingsBase 紧密结合,您可以在 ViewModel 中提及所有属性,并将其中的单个属性映射到单独的应用程序设置属性。您可以在之后直接使用您的设置进行出价,例如: {x:Static Settings.Default.Whatevs}。其他“保存”按钮单击事件或主窗口关闭事件,您可以保存所有设置,例如: Settings.Default.Save();

方法 - 2

一个更好的方法,我建议/更喜欢(如果我正在开发这个应用程序)是开发一个实现继承的包装类(例如:SettingProvider)(例如:ISettingProvider) 将所有设置显示为单独的属性,并且还有一个保存所有设置值的保存方法。您可以在 ViewModel 中使用这个包装类,以更好的方式处理所有命令和设置值。

这种方法的好处是,如果您决定将设置更改为数据库,则无需更改 ViewModel,因为所有工作都在 SettingProvider 类中完成。

我不确定,但根据查看您的代码,我假设您使用了 Approach-1。请发表您的评论和对此答案的任何反馈。我想知道您的想法,也许您有更简单有趣的方法来实现这一目标。

UPDATE-1

示例

用于演示的枚举

public enum MediaStatus
{
    Playing = 0,
    Stopped = 1,
    Paused = 2
}

界面

public interface ISettingProvider
{
    double Volumne { get; set; }
    string LastMediaUrl { get; set; }
    MediaStatus PlayingMediaStatus;

    void SaveSettings();
}

包装类

public class SettingProvider : ISettingProvider
{
    private double volumne;
    public double Volumne  // read-write instance property
    {
        get
        {
            return volumne;
        }
        set
        {
            volumne = value;
            Settings.Default.Volumne = volumne;
        }
    }

    private string lastMediaUrl;
    public string LastMediaUrl  // read-write instance property
    {
        get
        {
            return lastMediaUrl;
        }
        set
        {
            lastMediaUrl = value;
            Settings.Default.LastMediaUrl = lastMediaUrl;
        }
    }

    private MediaStatus playingMediaStatus;
    public MediaStatus PlayingMediaStatus  // read-write instance property
    {
        get
        {
            return playingMediaStatus;
        }
        set
        {
            playingMediaStatus = value;
            Settings.Default.PlayingMediaStatus = (int)playingMediaStatus;
        }
    }

    public void SaveSettings()
    {
        Settings.Default.Save();
    }

    //Constructor
    public SettingProvider()
    {
        this.Volumne = Settings.Default.Volumne;
        this.LastMediaUrl = Settings.Default.LastMediaUrl;
        this.PlayingMediaStatus = (MediaStatus)Settings.Default.PlayingMediaStatus;

    }
}

ViewModelBase 类

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

CommandHandler 类

public class CommandHandler : ICommand
{
    public event EventHandler CanExecuteChanged { add { } remove { } }

    private Action<object> action;
    private bool canExecute;

    public CommandHandler(Action<object> action, bool canExecute)
    {
        this.action = action;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return canExecute;
    }

    public void Execute(object parameter)
    {
        action(parameter);
    }
}

View 模型

public class SettingsViewModel : ViewModelBase
{
    SettingProvider objSettingProvider = new SettingProvider();

    public double Volumne 
    {
        get
        {
            return objSettingProvider.Volumne;
        }
        set
        {
            objSettingProvider.Volumne = value;
            OnPropertyChanged("Volumne");
        }
    }

    // Implementaion of other properties of SettingProvider with your ViewModel properties;


    private ICommand saveSettingButtonCommand;
    public ICommand SaveSettingButtonCommand
    {
        get
        {
            return saveSettingButtonCommand ?? (saveSettingButtonCommand = new CommandHandler(param => saveSettings(param), true));
        }
    }

    private void saveSettings()
    {
        objSettingProvider.SaveSettings();
    }
}

UPDATE-2

public interface ISettingProvider
{
    bool PauseOnLastFrame;
    bool IsAutoPlay;
    MediaStatus PlayingMediaStatus;

    void SaveSettings();
}


public class SettingProvider : ISettingProvider
{
    private bool pauseOnLastFrame;
    public bool PauseOnLastFrame  // read-write instance property
    {
        get
        {
            return pauseOnLastFrame;
        }
        set
        {
            pauseOnLastFrame = value;
            Settings.Default.PauseOnLastFrame = volumne;
        }
    }

    private bool isAutoPlay;
    public bool IsAutoPlay  // read-write instance property
    {
        get
        {
            return isAutoPlay;
        }
        set
        {
            isAutoPlay = value;
            Settings.Default.IsAutoPlay = volumne;
        }
    }
}

public class SettingsViewModel : ViewModelBase
{
    SettingProvider objSettingProvider = new SettingProvider();


    MediaStatus PlayingMediaStatus 
    {
        get
        {
            return objSettingProvider.PlayingMediaStatus;
        }
        set
        {
            if(value == MediaStatus.Paused)
                MediaPlayer.Pause();

            if(value == MediaStatus.Playing)
                MediaPlayer.Play();

            if(value == MediaStatus.Stopped)
                MediaPlayer.Stop();

            objSettingProvider.PlayingMediaStatus  = (int)value;

            OnPropertyChanged("PlayingMediaStatus");
        }
    }

    private string currentMediaFile;
    public string CurrentMediaFile
    {
        get
        {
            return currentMediaFile;
        }
        set
        {
            currentMediaFile  = value;

            MediaPlayer.Stop();
            MediaPlayer.Current = currentMediaFile;

            if(objSettingProvider.IsAutoPlay)
                MediaPlayer.Play();

            OnPropertyChanged("CurrentMediaFile");
        }
    }

    // Implementaion of other properties of SettingProvider with your ViewModel properties;


    private ICommand onMediaEndedCommand;
    public ICommand OnMediaEndedCommand
    {
        get
        {
            return onMediaEndedCommand ?? (onMediaEndedCommand = new CommandHandler(param => onMediaEnded(param), true));
        }
    }

    private void onMediaEnded()
    {
        if(objSettingProvider.PauseOnLastFrame)
        {
            PlayingMediaStatus = MediaStatus.Paused;
        }

        else if(PlayListViewModel.FilesCollection.Last().Equals(PlayListViewModel.FilesCollection.Current) && !Repeat)
        {
            PlayingMediaStatus = MediaStatus.Stopped;
        }

        else
        {
            CurrentMediaFile = PlayListViewModel.FilesCollection.MoveNext();
        }
    }
}

注意:这是我放在这里的详细示例,如果我遗漏了某个地方,也可以避免一些语法错误或命名错误。请更正。 我不知道您使用的是哪种媒体播放器设置。我拿了一些样本属性。这只是您可以为您的应用程序实现的结构示例。您可能需要更改更多代码来实现此结构。

关于c# - WPF 应用程序中的条件设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48664912/

相关文章:

java - 使用 JGoodies 绑定(bind)的只读绑定(bind)和单向转换器

c# - Visual Studio 2010 未在工具箱中显示打印选项卡的 Crystal Report Viewer?

c# - DateTime.ParseExact 上的 CultureInfo?

wpf - 如何获取 FlowDocument 中的元素/对象?

c# - WPF RightClick MouseBinding 发布?

haskell - 为什么我可以在 Haskell 中将值绑定(bind)到值?

c# - 如何将依赖注入(inject)应用于抽象工厂

c# - 显示小数而没有尾随零的最佳方法

c# - 如何避免鼠标在 Touch 上移动

JavaFX 将标签文本属性绑定(bind)到多个属性更改