【问题标题】:Using WPF xaml in MVP-VM Events or button click在 MVP-VM 事件或按钮单击中使用 WPF xaml
【发布时间】:2015-02-06 21:32:49
【问题描述】:

好的,所以我是(非常)WPF 新手,但使用 Win-forms 已有 13 年,所以没有新手。 我正在编写一个新系统,并决定使用 MVP-VM 模式打破 WPF 的僵局,因为我熟悉 MVP。

现在我还重用了我自己的(复合)架构,该架构在项目中具有 UI 或表示层,与 Presenters 和 View 模型分开。这种方法的主要好处之一是 Presenter 层或 Base 层具有所有表示/命令/控制器逻辑,并且不涉及 UI 问题。主要想法是该层不引用任何 UI 程序集,如 Winforms 或 WPF。

问题: 在 Xaml 中,我有一个菜单项“退出”,我想将其绑定到视图模型。我看到的每个示例都使用 ICommand.. 它位于 Presentation.core... 视图模型位于表示层中,因此没有对 Presentation.Core.. 的引用。

到目前为止的 Xaml 是

<Window x:Class="Homestead.Wpf.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="244" Width="490" xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="23"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="23" />
    </Grid.RowDefinitions>
    <Menu Grid.Row="0">
        <MenuItem Header="File">
            <MenuItem Header="Exit"  />
        </MenuItem> 
    </Menu>
    <StatusBar Grid.Row="2"  >
        <StatusBarItem   >
            <TextBlock  Text="{Binding Path=StatusMessage}" />
        </StatusBarItem>
        <StatusBarItem  HorizontalAlignment="Right" MinWidth="120">
            <TextBlock  Text="{Binding Path=UserName}" />
        </StatusBarItem>
    </StatusBar>
</Grid>

到目前为止的视图模型是

public class ShellViewModel : ViewModelBase
{

    #region Private Variables

    private string _status = string.Empty;
    private string _userName;

    #endregion

    #region Public Properties

    public string StatusMessage
    {
        get { return _status; }
        set
        {
            _status = value;
            OnPropertyChanged("StatusMessage");
        }
    }

    public string UserName
    {
        get { return _userName; }
        set
        {
            _userName = value;
            OnPropertyChanged("UserName");
        }
    }


    #endregion

    #region Commands

    // No reference to ICommand... WTF

    #endregion
}
  1. 这种模式有什么替代方案吗..(不使用代码隐藏)
  2. 这如何与在运行时添加的菜单项一起工作,有趣的是有一种方法。

我必须重新设计或打破设计模式才能使用 WPF?请指导我。

我可以看到一种可能性,那就是接口出 ViewModel 以及 View。我有一个控制器,它创建通常将视图的实现传递给演示者的 Presenter。即典型的 Presenter 构造函数是

    public ErrorMessagePresenter(IErrorMessageView view)
    {
        View = view;
        View.Presenter = this;            
    }

控制器代码是这样的

    public ErrorMessagePresenter CreateErrorPresenter()
    {
        return new ErrorMessagePresenter(_viewFactory.CreateErrorMessageView());
    }

现在我知道这是相反的,但实际上 UI 层只关心 UI 问题,包括导航在内的所有其他内容都在 Base 层或以下处理..

【问题讨论】:

    标签: c# wpf xaml icommand


    【解决方案1】:

    WPF 中最常见的模式是 Model-View-ViewModel,在这种模式中,presenter 已被移除,取而代之的是知识更丰富的视图模型,它确实知道 ICommand(它是一个契约,共享视图层作为交流动作的一种方式,这证明了视图模型知道它是正确的)。

    您可以尝试通过实现行为和数据触发器来强制应用不使用 ICommand如果您打算在未来继续开发 WPF 应用程序(或 Windows 应用商店应用程序,通常也使用 MVVM),则可持续发展。

    我建议您考虑使用 NuGet 在您的项目中合并一个像 MVVM-light 这样的框架,这样您就可以从一套完善的类、模式和实用程序的基础开始,这些类、模式和实用程序已经适应 WPF 作为一种技术多年来一直没有尝试将您熟悉的“球形”框架锤入WPF(形象地说)的“方形”腔中。

    当我开始使用它时,我学到了一个艰难的方法,即试图将我的经验和习惯从 WinForms 带到 WPF 只会带来麻烦,所以你越早开始平静下来,因为你所做的大部分工作都赢了'不适用于 WPF,对你的精神健康更好。

    当然,模式就是模式,它们可以在多种环境中以不同的方式应用,但现实情况是 WPF 已经为某些事情提供了插件,可以以某种方式工作,而试图与之抗衡只会为您作为开发人员和架构师提供更多工作,因此最好顺其自然并适应 XAML 世界中最常见的做事方式。

    【讨论】:

      【解决方案2】:

      为您提供一些快速解决方案:

      • 1 - 如果您的目标是Portable Class Library,则可以使用System.Windows.Input.ICommand。这可能是可能的,也可能不是,取决于您项目的其他要求,但如果可以选择,则确实建议您将所有 ViewModel 和“UI 目标”代码放在 PCL 中,因为根据定义,这些代码是最可重用且与平台无关的您可以在 .Net 中创建的程序集类型,不仅支持 Windows .Net 场景,还支持通过 Xamarin 进行移动。

      • 2 - 通过依赖注入或服务定位器模式抽象出 ICommand 接口。

      • 3:添加对 PresentationCore.dll 的引用,但请确保您没有使用除 ICommand 之外的任何内容。


      为了回答您的问题 #2,菜单:ListBoxes、ComboBoxes、TreeViews 以及 WPF 中任何其他基于项目的 UI 元素都派生自 ItemsControl 类。它提供了一种从数据项集合动态生成 UI 元素的抽象方法。

      请参阅this blog series 以获得非常全面的解释。 ItemsControl 是最强大的 WPF 功能之一,掌握它会非常有益。我使用它创建了各种各样的东西,从面包屑栏到“标记控件”(类似于 StackOverflow 的标签选择),到棋盘到 diagram designers

      基本上,您将创建一个具有表示菜单项的简单属性的类(带有文本、图像和单击菜单项时要执行的 ICommand),并将此类的实例放入 ObservableCollection&lt;T&gt;,它支持WPF 数据绑定到集合。


      附带说明,您的控制器创建了演示者和视图,并将视图与 ViewModel 和演示者方法相关联,而这一切都是不需要的。它创建了一个过于复杂、完全不可维护的场景,您需要在每次需要显示视图时手动执行此操作。

      WPF 使用DataTemplates 解决了这个问题。请参阅this answer 以获得一个非常简单的使用示例。

      事实上,在 WPF 中甚至根本不需要 Presenter 的整个概念。由于您的 View 使用 DataBinding “粘合”到其底层 ViewModel,因此无需手动“管道”代码或来回传递数据。

      【讨论】:

        猜你喜欢
        • 2014-02-17
        • 1970-01-01
        • 1970-01-01
        • 2014-09-26
        • 2015-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        相关资源
        最近更新 更多