【问题标题】:WPF MVVM Correct way to design view-viewmodel-view communication [closed]WPF MVVM 设计视图-视图模型-视图通信的正确方法 [关闭]
【发布时间】:2017-12-13 06:11:48
【问题描述】:

我有

  • 主视图
  • 菜单视图
  • 视图模型
  • 内容视图

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

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

我尝试将 ContentView 的 DataContext 设置为 ViewModel 的 FlowDocument (这可能违反了 MVVM 模式),但由于 RichTextBox 的 Document 无法绑定到 ViewModel 的 FlowDocument 导致失败。

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

这里是简化的示例代码

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!");
    }
}

【问题讨论】:

  • 如何设计代码是见仁见智的问题。但是,对我来说,视图模型仅抽象命令(即接收命令的用户交互)并具有某种机制(如视图事件)(拥有并知道要打印的流文档)订阅似乎是合理的并自行处理。打印更多是“视图”的事情,而不是“数据”的事情,所以对我来说,在视图代码而不是模型代码中处理它是有意义的。
  • @PeterDuniho 我理解您的意见是合理的。但由于定制打印机(nemonic 打印机),我的项目有一个复杂的打印过程。我需要向 4 个方向旋转纸张,设置要打印的自定义纸张尺寸,设置纸张边距并记录打印计数,以通知用户清洁打印机标题。因此,我决定在 ViewModel 中操作打印过程,而不是在 View 中。打印过程需要一些属性,由其他视图设置。
  • 看看这里stackoverflow.com/a/28815689/2389106。如果您将设计这种或类似的方式,您应该可以访问您的 FlowDocument
  • @Sasha 我不想创建 MenuViewModelContentViewModel。我只有一个 ViewModel。问题是在 MenuView 触发事件,但我需要 ContentView's FlowDocument 才能打印内容。 (也许我的尝试可能会误导您的理解。对此深表歉意)
  • @ibocon 此链接显示了使用 Vm 和 Views 的方式,而不是如何实现 MenuViewModel 或 MenuView ... 至于你的问题不清楚,如何实现 ContentView.xaml。它是窗口(MenuView)内的UserControl吗?如果是,你如何加载它来查看?

标签: c# wpf xaml mvvm


【解决方案1】:

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

我只是快速尝试一下。

在您的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 绑定到 FlowDocument 为 CommandParamater 或在单击按钮时使用它。

【讨论】:

  • 谢谢!它适用于后面的代码。但是,如何在 XAML 中绑定 FlowDocument? {Binding Path=FlowDocument} 不起作用。
  • 你的意思是命令参数?
  • 是的,Command="{Binding PrintCommand}" CommandParameter="{/* */}"
  • 你必须使用控件的相对源。
猜你喜欢
  • 2014-07-10
  • 2014-10-11
  • 2018-08-02
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 1970-01-01
  • 2016-04-26
相关资源
最近更新 更多