WPF MVVM设计view-viewmodel-view通信的正确方法

时间:2017-12-13 06:11:49

标签: c# wpf xaml mvvm

我有

  • 的MainView
  • MenuView
  • 视图模型
  • 内容查看

MainView 是Window,其中包括MenuView& ContentView为 UserControl
MenuView 有一个打印按钮,可以绑定到ViewModel的打印命令。
ViewModel 有一个打印命令,需要RichTextBox的FlowDocument才能打印。
ContentView 有一个RichTextBox,需要打印。

我可以绑定MenuView和ViewModel。但是,我无法获得ContentView的FlowDocument。

我尝试将ContentView的DataContext设置为ViewModel的FlowDocument(可能违反了MVVM模式),但它失败了,因为RichTextBox的Document无法绑定到ViewModel' s的FlowDocument。

因此,我需要帮助设计MVVM模式以打印RichTextBox的FlowDocument。

这是简化的示例代码

ViewModel.cs

class ViewModel
{
     public ICommand PrintCommand;
     //Fail binding to ContentView's RichTextBox
     public FlowDocument FlowDocument;

     public ViewModel 
     {
         PrintCommand = new PrintCommand();
     }
}

MenuView.xaml

<Button x:Name="ButtonPrint" Command="{Binding PrintCommand}" 
 CommandParameter="/* How to get ContentView's FlowDocument */" >

MenuView.xaml.cs

private void ButtonPrint_Click(object sender, RoutedEventArgs e)
{
    (this.DataContext as MainViewModel).PrintCommand.Execute(/* How to get ContentView's FlowDocument */);
}

ContentView.xaml

<RichTextBox>
    <FlowDocument x:Name="FlowDocument">
        <Paragraph>
            <Run Text="RichTextBox"/>
        </Paragraph>
    </FlowDocument>
</RichTextBox>

PrintCommand.cs

class PrintCommand : ICommand
{
    private FlowDocument flowDocument; 
    public PrintCommand(FlowDocument flowDocument)
    {
        this.flowDocument = flowDocument;
    }

    public void Execute(object parameter)
    {
        //Execute Print!
        Console.Write("Print!");
    }
}

1 个答案:

答案 0 :(得分:2)

如果我理解正确,您可以执行以下操作。

我只是快速尝试一下。

ContentControl上,您宣布read only dependency property

    public ContentView()
    {
        InitializeComponent();
        this.FlowDocument = this.RealFlowDocument;
    }


    private static readonly DependencyPropertyKey FlowDocumentPropertyKey =
        DependencyProperty.RegisterReadOnly("FlowDocument", typeof(FlowDocument), typeof(ContentView),
            new FrameworkPropertyMetadata());


    public static readonly DependencyProperty FlowDocumentProperty
        = FlowDocumentPropertyKey.DependencyProperty;

    public FlowDocument FlowDocument
    {
        get { return (FlowDocument)GetValue(FlowDocumentProperty); }
        protected set { SetValue(FlowDocumentPropertyKey, value); }
    }

MenuView中,你会做类似的事情(不是只读)

    private static readonly DependencyProperty FlowDocumentProperty =
        DependencyProperty.Register("FlowDocument", typeof(FlowDocument), typeof(MenuView),
            new FrameworkPropertyMetadata());


    public FlowDocument FlowDocument
    {
        get { return (FlowDocument)GetValue(FlowDocumentProperty); }
        set { SetValue(FlowDocumentProperty, value); }
    }

最后,您可以在MainView

中同时连接两者
<Grid>
    <local:ContentView x:Name="contentView"/>
    <local:MenuView FlowDocument="{Binding ElementName=contentView, Path=FlowDocument, Mode=OneWay}"/>
</Grid>

您可以将MenuView中的CommandParamater绑定到FlowDocument curl --data "birthyear=1905&press=%20OK%20" ,或者在按钮点击时使用它。