У меня есть проект 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
Edit # 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");
}
}
Но я заметил, что установщик для свойства зависимостей в моем представлении code-behind никогда не выполняется.Я узнал, что эти сеттеры не выполняются при вызове извне.Как мне заставить программный код представления реагировать на внешние изменения и использовать методы, упомянутые в сеттере выше?то есть
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();
Обратите внимание, что вы не можете вызывать ни одного статического метода напрямую из static OnPatternChanged.. так что вам нужно преобразовать отправителя в объект и вызвать методы его члена.