如何在不使用依赖项属性的情况下将view元素中的属性绑定到view-model属性?

时间:2019-07-03 16:12:42

标签: c# wpf mvvm binding element

我有一个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并调用其成员方法。

0 个答案:

没有答案
相关问题