Как связать свойство в элементе представления со свойством view-model без использования свойства зависимости? - PullRequest
0 голосов
/ 03 июля 2019

У меня есть проект 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.. так что вам нужно преобразовать отправителя в объект и вызвать методы его члена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...