C# 如何使用ViewModel优先方法从ViewModel调用视图方法
我正在使用框架开发一个WPF应用程序,其体系结构基于模型-视图-模型-模式原则 以下XAML代码是my View ViewModel关系的示例:C# 如何使用ViewModel优先方法从ViewModel调用视图方法,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我正在使用框架开发一个WPF应用程序,其体系结构基于模型-视图-模型-模式原则 以下XAML代码是my View ViewModel关系的示例: <... .Resources> <DataTemplate DataType="{x:Type viewm:MediaElementViewModel}"> <view:MediaElement/> </DataTemplate> </... .Resources>
<... .Resources>
<DataTemplate DataType="{x:Type viewm:MediaElementViewModel}">
<view:MediaElement/>
</DataTemplate>
</... .Resources>
我知道,在构造具体的MediaElement
时,可以通过分配MediaElement
实例的DataContext
属性从ViewModel调用视图方法,不幸的是,这不是我的解决方案
例如,视图方法是MediaElement
,例如Play()
、Pause()
、Focuse()
或任何其他“纯”UI方法
非常感谢。视图引用了您的视图模型,但对其没有内在知识或访问权限 如果您建议的方法是show和close,那么通过绑定到visibility属性的视图模型来处理这个问题就很简单了
其他可能有用的概念是数据触发器,它允许您通过动画行为更新视图、设置属性或从许多条件触发。视图引用了视图模型,但对其没有内在知识或访问权限 如果您建议的方法是show和close,那么通过绑定到visibility属性的视图模型来处理这个问题就很简单了
其他可能有用的概念是数据触发器,它允许您通过动画行为更新视图、设置属性或从许多条件触发。我找到了一个有效的解决方案,我将保留它的答案,直到找到更好的解决方案 解决方案基于定制 需要注意的是,问题和答案在全局范围内,而不是
MediaElement
范围内。因此,此解决方案与支持ViewModel First方法的每个框架元素
派生控件完全相关
为了清晰起见,我没有删除任何代码。
ViewTemplates.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
以下是上述解决方案使用的示例:
App.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
main window.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
MainViewModel.cs
public MediaElementViewModel()
{
Volume = 0.5;
}
private Uri _source;
public Uri Source
{
get { return _source; }
set
{
_source = value;
RaisePropertyChanged("Source");
}
}
private double _volume;
public double Volume
{
get { return _volume; }
set
{
_volume = value;
RaisePropertyChanged("Volume");
}
}
public Action Play { get; set; }
public Action Stop { get; set; }
public Func<bool> Focus { get; set; }
public MediaElementBehavior()
{
}
protected override void OnAttached()
{
base.OnAttached();
MediaElement player = (MediaElement)this.AssociatedObject;
MediaElementViewModel viewModel = (MediaElementViewModel)this.AssociatedObject.DataContext;
player.Dispatcher.Invoke(() =>
{
// backing up the player methods inside its view-model.
if (viewModel.Play == null)
viewModel.Play = player.Play;
if (viewModel.Stop == null)
viewModel.Stop = player.Stop;
if (viewModel.Focus == null)
viewModel.Focus = player.Focus;
});
}
protected override void OnDetaching()
{
base.OnDetaching();
}
public MainViewModel()
{
CurrentMediaElement = new MediaElementViewModel();
}
private MediaElementViewModel _currentMediaElement;
public MediaElementViewModel CurrentMediaElement
{
get { return _currentMediaElement; }
set
{
_currentMediaElement = value;
RaisePropertyChanged("CurrentMediaElement");
}
}
private RelayCommand _setSourceCommand;
public ICommand SetSourceCommand
{
get
{
return _setSourceCommand ??
(_setSourceCommand = new RelayCommand(SetSourceExecute));
}
}
private RelayCommand _playCommand;
public ICommand PlayCommand
{
get
{
return _playCommand ??
(_playCommand = new RelayCommand(PlayExecute));
}
}
private RelayCommand _stopCommand;
public ICommand StopCommand
{
get
{
return _stopCommand ??
(_stopCommand = new RelayCommand(StopExecute));
}
}
private RelayCommand _focusCommand;
public ICommand FocusCommand
{
get
{
return _focusCommand ??
(_focusCommand = new RelayCommand(FocusExecute));
}
}
/// <summary>
/// Invoked whenever focusing media element;
/// </summary>
private void FocusExecute()
{
bool isFocused = this.CurrentMediaElement.Focus();
}
/// <summary>
/// Invoked whenever setting a media source.
/// </summary>
private void SetSourceExecute()
{
// Assume the media file location is Debug/bin/Resources/
this.CurrentMediaElement.Source = new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\media.mp3");
}
/// <summary>
/// Invoked whenever playing media.
/// </summary>
private void PlayExecute()
{
this.CurrentMediaElement.Play();
}
/// <summary>
/// Invoked whenerver stopping media.
/// </summary>
private void StopExecute()
{
this.CurrentMediaElement.Stop();
}
public主视图模型()
{
CurrentMediaElement=新MediaElementViewModel();
}
私有MediaElement视图模型_currentMediaElement;
公共MediaElement视图模型CurrentMediaElement
{
获取{return\u currentMediaElement;}
设置
{
_currentMediaElement=值;
RaisePropertyChanged(“CurrentMediaElement”);
}
}
私人中继通信(u setSourceCommand);;
公共ICommand设置资源命令
{
得到
{
返回设置资源命令??
(_setSourceCommand=newrelaycommand(SetSourceExecute));
}
}
专用中继命令(playCommand);;
公共ICommand播放命令
{
得到
{
返回\u playCommand??
(_playCommand=newrelaycommand(playcexecute));
}
}
专用中继命令_stopCommand;
公共ICommand stop命令
{
得到
{
返回_stop命令??
(_stopCommand=new RelayCommand(StopExecute));
}
}
私人关系社区(focusCommand);;
公共ICommand FocusCommand
{
得到
{
返回焦点命令??
(_focusCommand=newrelaycommand(FocusExecute));
}
}
///
///在聚焦媒体元素时调用;
///
私有void FocusExecute()
{
bool isFocused=this.CurrentMediaElement.Focus();
}
///
///在设置媒体源时调用。
///
私有void SetSourceExecute()
{
//假设媒体文件位置为Debug/bin/Resources/
this.CurrentMediaElement.Source=新Uri(AppDomain.CurrentDomain.BaseDirectory+“Resources\\media.mp3”);
}
///
///在播放媒体时调用。
///
私有void PlayExecute()
{
这个.CurrentMediaElement.Play();
}
///
///在停止媒体时调用。
///
私有void StopExecute()
{
这个.CurrentMediaElement.Stop();
}
如您所见(在MainViewModel.cs),我使用ViewModel-First方法从ViewModel调用了“纯”视图方法。(
PlayExecute
,StopExecute
和FocusExecute
)。我找到了一个有效的解决方案,在找到更好的解决方案之前,我会保留它的答案
解决方案基于定制
需要注意的是,问题和答案在全局范围内,而不是MediaElement
范围内。因此,此解决方案与支持ViewModel First方法的每个框架元素
派生控件完全相关
为了清晰起见,我没有删除任何代码。
ViewTemplates.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
以下是上述解决方案使用的示例:
App.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
main window.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<DataTemplate DataType="{x:Type local:MediaElementViewModel}">
<MediaElement Source="{Binding Source}" Volume="{Binding Volume}"
LoadedBehavior="Manual" UnloadedBehavior="Manual">
<i:Interaction.Behaviors>
<local:MediaElementBehavior/>
</i:Interaction.Behaviors>
</MediaElement>
</DataTemplate>
</ResourceDictionary>
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ViewTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Content="{Binding CurrentMediaElement}"/>
<Button Grid.Row="1" Grid.Column="0" Content="Set Source" Command="{Binding SetSourceCommand}"/>
<WrapPanel Grid.Row="1" Grid.Column="2">
<Button Grid.Row="1" Grid.Column="2" Content="Stop" Command="{Binding StopCommand}"/>
<Button Content="Focus" Command="{Binding FocusCommand}"/>
</WrapPanel>
<Button Grid.Row="1" Grid.Column="1" Content="Play" Command="{Binding PlayCommand}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding CurrentMediaElement.Source}" TextWrapping="Wrap"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding ElementName=SliderVolume, Path=Value}"/>
<Slider x:Name="SliderVolume" Value="{Binding CurrentMediaElement.Volume}" Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" Orientation="Horizontal"/>
</Grid>
</Window>
MainViewModel.cs
public MediaElementViewModel()
{
Volume = 0.5;
}
private Uri _source;
public Uri Source
{
get { return _source; }
set
{
_source = value;
RaisePropertyChanged("Source");
}
}
private double _volume;
public double Volume
{
get { return _volume; }
set
{
_volume = value;
RaisePropertyChanged("Volume");
}
}
public Action Play { get; set; }
public Action Stop { get; set; }
public Func<bool> Focus { get; set; }
public MediaElementBehavior()
{
}
protected override void OnAttached()
{
base.OnAttached();
MediaElement player = (MediaElement)this.AssociatedObject;
MediaElementViewModel viewModel = (MediaElementViewModel)this.AssociatedObject.DataContext;
player.Dispatcher.Invoke(() =>
{
// backing up the player methods inside its view-model.
if (viewModel.Play == null)
viewModel.Play = player.Play;
if (viewModel.Stop == null)
viewModel.Stop = player.Stop;
if (viewModel.Focus == null)
viewModel.Focus = player.Focus;
});
}
protected override void OnDetaching()
{
base.OnDetaching();
}
public MainViewModel()
{
CurrentMediaElement = new MediaElementViewModel();
}
private MediaElementViewModel _currentMediaElement;
public MediaElementViewModel CurrentMediaElement
{
get { return _currentMediaElement; }
set
{
_currentMediaElement = value;
RaisePropertyChanged("CurrentMediaElement");
}
}
private RelayCommand _setSourceCommand;
public ICommand SetSourceCommand
{
get
{
return _setSourceCommand ??
(_setSourceCommand = new RelayCommand(SetSourceExecute));
}
}
private RelayCommand _playCommand;
public ICommand PlayCommand
{
get
{
return _playCommand ??
(_playCommand = new RelayCommand(PlayExecute));
}
}
private RelayCommand _stopCommand;
public ICommand StopCommand
{
get
{
return _stopCommand ??
(_stopCommand = new RelayCommand(StopExecute));
}
}
private RelayCommand _focusCommand;
public ICommand FocusCommand
{
get
{
return _focusCommand ??
(_focusCommand = new RelayCommand(FocusExecute));
}
}
/// <summary>
/// Invoked whenever focusing media element;
/// </summary>
private void FocusExecute()
{
bool isFocused = this.CurrentMediaElement.Focus();
}
/// <summary>
/// Invoked whenever setting a media source.
/// </summary>
private void SetSourceExecute()
{
// Assume the media file location is Debug/bin/Resources/
this.CurrentMediaElement.Source = new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\media.mp3");
}
/// <summary>
/// Invoked whenever playing media.
/// </summary>
private void PlayExecute()
{
this.CurrentMediaElement.Play();
}
/// <summary>
/// Invoked whenerver stopping media.
/// </summary>
private void StopExecute()
{
this.CurrentMediaElement.Stop();
}
public主视图模型()
{
CurrentMediaElement=新MediaElementViewModel();
}
私有MediaElement视图模型_currentMediaElement;
公共MediaElement视图模型CurrentMediaElement
{
获取{return\u currentMediaElement;}
设置
{
_currentMediaElement=值;
RaisePropertyChanged(“CurrentMediaElement”);