我有一个WPF MVVM项目,该项目的属性类型为OudPattern
。
我想将此属性绑定到视图中的OudPatternEditor1
上的UserControl
。有什么办法可以使用INotifyPropertyChange
来做到这一点。因为我已经在项目中使用它。
请注意,OudPatternEditor1
是在启动时使用new OudPattern()
实例化的。但是此模式可以由用户更改。因此我需要在视图模型中同时更新此属性,OudEditor1
也要更新。
我通过将视图传递给视图模型并每次更新该属性来解决了这个问题。但是我知道这种方法违反了将视图和视图模型分离的MVVM原理。
我也尝试使用依赖项属性来解决此问题,但未能获得解决方案。
自定义用户控件XAML
<UserControl x:Class="MyOudTeacher.OudMachine.OudPatternEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Visibility="Visible">
<Canvas x:Name="oudGridCanvas"/>
</UserControl>
隐藏代码
public partial class OudPatternEditor : UserControl
{
private OudPattern oudPattern;
private double gridSquareWidth = 15;// my code: default 20
private double namesColumnWidth = 50;//my code: default 100
public OudPatternEditor()
{
InitializeComponent();
this.oudPattern = new OudPattern();
DrawNoteNames();
DrawPattern(namesColumnWidth);
DrawGridLines(namesColumnWidth);
}
public OudPattern OudPattern
{
get { return oudPattern; }
set {
oudPattern = value;
UpdateHitView();
}
}
/* more code... */
}
视图XAML
<UserControl x:Class="MyOudTeacher.OudMachine.OudMachineView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500" xmlns:my="clr-namespace:MyOudTeacher.OudMachine">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="262*" />
</Grid.RowDefinitions>
<my:OudPatternEditor Grid.Row="1" HorizontalAlignment="Left" Margin="20" x:Name="oudPatternEditor1" VerticalAlignment="Top"/>
<StackPanel Orientation="Horizontal">
<Button Command="{Binding StopCommand}" Margin="2" ToolTip="Stop">
<Rectangle Fill="DarkBlue" Width="15" Height="15" Margin="3" RadiusX="2" RadiusY="2"/>
</Button>
<!-- more code... -->
视图模型
class OudMachineViewModel : ViewModelBase, IDisposable
{
private IWavePlayer waveOut;
private OudPattern pattern;
private OudPatternEditor OudPatternEditor;
private OudPatternSampleProvider patternSequencer;
private int tempo;
private string selectedFile;
public ICommand PlayCommand { get; }
public ICommand StopCommand { get; }
public ICommand UpdateXmlCommand { get; }
public ICommand OpenFileCommand { get; }
public ICommand PauseCommand { get; }
public OudMachineViewModel(OudPatternEditor oudPatternEditor)
{
this.OudPattern = oudPatternEditor.OudPattern;
this.OudPatternEditor = oudPatternEditor;
Tempo = OudPattern.ScoreHits.ScaledTempo;
PlayCommand = new DelegateCommand(Play);
StopCommand = new DelegateCommand(Stop);
OpenFileCommand = new DelegateCommand(OpenFile);
PauseCommand = new DelegateCommand(Pause);
}
public OudPattern OudPattern
{
get { return pattern; }
set
{
pattern = value;
OnPropertyChanged("OudPattern");
}
}
private void UpdateSelectedFile()
{
OudPattern = new OudPattern(selectedFile);
OudPatternEditor.OudPattern = this.OudPattern;
Tempo = OudPattern.ScoreHits.ScaledTempo;
}
/* more code... */
正确的方法是不要将OudEditor
传递给视图模型构造函数。因为这是针对MVVM的。我希望找到一种将OudEditor1.OudPattern
绑定到ViewModel.OudPattern
编辑#1:
我能够添加一个依赖项属性并实现我想要的。添加的代码很简单:
查看背后的代码:
public OudPattern OudPattern
{
get { return (OudPattern)GetValue(OudPatternProperty); }
set
{
SetValue(OudPatternProperty, value);
DrawNewPattern();
UpdateHitView();
}
}
public static readonly DependencyProperty OudPatternProperty =
DependencyProperty.Register("OudPattern", typeof(OudPattern), typeof(OudPatternEditor),
new PropertyMetadata(default(OudPattern)));
查看上面的XAML,已修改:
<my:OudPatternEditor Grid.Row="1" HorizontalAlignment="Left" Margin="20" x:Name="oudPatternEditor1" VerticalAlignment="Top" OudPattern="{Binding OudPattern}"/>
视图模型:
public OudPattern OudPattern
{
get { return pattern; }
set
{
pattern = value;
OnPropertyChanged("OudPattern");
}
}
但是我注意到在我后面的视图代码中,依赖属性的设置器永远不会执行。我了解到,从外部调用这些设置程序时不会执行。如何使背后的视图代码对外部更改做出反应,以及上面设置方法中提到的方法?即
DrawNewPattern();
UpdateHitView();
编辑#2: 我找到了关于依赖属性设置器的最后一个问题的答案。感谢Elgonzo指出我可以使用属性更改的回调。
应该修改代码以添加OnPatternChanged回调
public static readonly DependencyProperty OudPatternProperty =
DependencyProperty.Register("OudPattern", typeof(OudPattern), typeof(OudPatternEditor),
new PropertyMetadata(default(OudPattern),OnPatternChanged));
private static void OnPatternChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myObject = (OudPatternEditor)d;
myObject.DrawNewPattern();
myObject.UpdateHitView();
请注意,您不能直接从静态OnPatternChanged ..直接调用静态方法,因此您需要将发送方转换为object并调用其成员方法。