【问题标题】:WPF C#: MVVM - Passing on the Sudoku from ViewModel -> ViewWPF C#:MVVM - 从 ViewModel 传递数独 -> 视图
【发布时间】:2017-03-01 09:44:37
【问题描述】:

所以,我有一个关于 MVVM+WPF 的问题:目前,我有一个 Sudoku 工作,并且我设法以我喜欢在 WPF 中使用 Sudoku 的方式生成了一个 Sudoku。

我的应用程序中的数独 WPF 图像

问题是网格是由我在 MainWindow.xaml.cs 文件中编写的一些代码创建的,我认为它应该在 ViewModel 中。 MainWindow.xaml.cs 中有问题的代码:

namespace SodukoWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private SudokoGameDesu sudokuAdapter;

        public MainWindow()
        {
            InitializeComponent();
            sudokuAdapter = new SudokoGameDesu();


            CreateDynamicWPFGrid();
        }

        private void CreateDynamicWPFGrid()
        {
            // Create 9 rows & columns
            for (int i = 0; i < 9; i++)
            {
                // Create column
                sudokuGrid.ColumnDefinitions.Add(new ColumnDefinition());
            ... etc.

恕我直言,CreateDynamicWPFGrid() 应该移到我的 ViewModel 中。至少这是我认为这段代码最适合的地方。

namespace SodukoWPF.ViewModels
{
    public class SudokoPresenter : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        // TODO get .xaml.cs code in here

        public SudokoPresenter()
        {
            //CreateDynamicWPFGrid();
        }

在 CreateDynamicWPFGrid() 方法中,我使用 sudokuGrid,这是我的 .xaml 中的一个字段,因此我的代码也知道应该将我的 textBoxes/Blocks 添加到哪个网格中。

<Grid x:Name="contentGrid" HorizontalAlignment="Left" Height="570" Margin="0,0,0,0" VerticalAlignment="Top" Width="500">
        <Grid x:Name="sudokuGrid" HorizontalAlignment="Left" Height="420" Margin="0,50,0,0" VerticalAlignment="Top" Width="488">
        </Grid>

现在,无法从 .xaml.cs 代码外部访问此网格(当然)。所以在这一点上,我生成自己的 xaml 的方法(因为我认为这不能仅通过 xaml + 绑定来完成)给我一些问号,我是否正确应用了 MVVM。

理论上 ViewModel 不应该知道 View,但我仍然认为生成的 .xaml 应该在我的 SudokuPresenter - ViewModel 中,而不是在我认为最好应该为空的 .xaml.cs 中。

我还没有弄清楚如何将 SudokuGrid 导入到我的 ViewModel,但我的 MVVM 方法很可能一开始就有问题或被我误解了。

希望有人可以帮助我,这篇文章或多或少对我的困境有意义=)

(关于生成我自己的 .xaml 的 MVVM 方法 + 如果我做得或多或少正确,如何访问 sudokuGrid)

【问题讨论】:

  • 我觉得你不了解 MVVM 模式。你绝对不应该在你的 ViewModel 中有任何 UI 问题。您的数独数据应该在您的 ViewModel 中,而网格本身应该在您的 xaml 中。你正确的一件事是关于你的 xaml.cs :它应该是空的,你应该使用模板或自定义控件来构建带有绑定的数独网格。
  • 关于网格的事情是它是生成的,所以我不确定如何将数独绑定到网格。此外,网格使用 81 个矩形、9 个黑色矩形、81 个文本框/文本块,我不知道如何在不编写大量 .xaml 的情况下在网格中获得它。我认为生成将是最简单/最智能的方法,但这可能是我不正确地知道如何执行 WPF 和 xaml E:每次应用程序启动时都会生成网格/数独(+ 传递给视图),它当按下重置按钮时,也应该再次生成。
  • 欢迎来到 StackOverflow!我很高兴看到仍有新用户花时间让他们的问题易于阅读并很好地解释!现在的问题是:为什么不构建一个名为 cell 的对象,该对象将保存所有单元格数据(值、位置等)并在您的 ViewModel 中创建一个单元格集合,您将使用绑定填充一个统一的网格?跨度>
  • 这实际上听起来像是一个我没有想到的好主意,主要是因为我对 WPF 和 Xaml tbh 缺乏经验。让我朝着这个方向思考应该可以防止我现在遇到的整个问题,所以谢谢! =)。只需要谷歌并弄清楚如何让这些自定义单元格工作,但我想我可以完成它。
  • 当您的网格并不总是相同时,通过代码生成网格的想法很有用,所以为什么不在 xaml 中编写您的网格。当数据发生变化时,开始新游戏时不需要生成网格,只需更改您的数据即可。如果您希望继续使用代码生成的网格,您也可以通过代码创建绑定:MSDN - How to: Create a Binding in Code

标签: c# wpf xaml mvvm


【解决方案1】:

MVVM(以及一般的 wpf)的概念与您所展示的略有不同。

让我为您提供 MVVM 的每个元素在您的情况下应如何发挥作用的细分:

  1. 模型 该模型几乎是您的数据持有者。它是对象,其中包含有关程序关键元素的信息,将在 ViewModel(s) 中进一步使用和处理。

在您的情况下,最基本的情况是单元格类和网格类。 Cell 类将包含基本的单元格信息:值、位置。 Grid 类将包含一组单元格,以及 ex 的方法。用于检索单元格 x 留给单元格 y,检索包含在框(3x3 数独方块)中的单元格等。

  1. 视图模型

这将包含您的程序逻辑。现在,不要弄错了——这应该只包含当你在 GUI 的单元格中输入一个值时发生的事情——例如运行评估器以确保整个网格的正确性。

这也应该包含 Grid 类本身 - 所以它可以被 GUI 引用。

  1. 观点:

这主要是您的 XAML。只要您不深入研究 IoC 容器、依赖注入(我认为您的第一个实际 MVVM 程序不应该这样做),您的 xaml.cs(视图代码隐藏)在大多数情况下都会保留没有任何变化。

视图可以包含一个 UniformGrid,它有一个用于每个单元格外观的特定模板,并且该 uniformgrid 将绑定到单元格集合 - 它将位于您的 Grid 模型类中。

现在,大多数没有 MVVM 背景的人会说:“但我可以给它们命名吗?我将如何引用那些抽象的、动态创建的单元类?”

这样,UI 将自己创建所有单元格,并且每个单元格都会自动分配给某个单元格类,因此它会知道您刚刚输入的值将存储在单元格类的 X 实例中.

您的目标是设计方法/类结构,这将允许您轻松地“间接”执行任何所需的操作(例如,位于 Game 类中并检查框(3x3 网格)中的所有单元格的方法根据数独规则输入。

我希望你掌握了这个概念,请随时提出任何问题,我很乐意提供示例代码来更好地解释这些特定概念。

【讨论】:

  • 我认为你告诉我的事情现在会帮助我,给我一个很好的起点。我对忘记建立一个合适的模型类感到很愚蠢。 E:我的意思是。有一个模型类,但它只是用于生成数独并检查正确 x、y 位置的变量是否错误/正确的实际 GameClass 的适配器。所以我只需要以 MVVM 结构正常工作的方式构建应用程序。拥有一个 Cell 类,也许/可能还有 Grid 类应该仍然有很大帮助,解决我的 MVVM 问题和所有这些问题,非常感谢;d
  • 感谢您接受我的回答,但我仍然认为您可能需要一些指导。今晚有空时,我会尝试用示例更新我的答案。
  • 公平地说,我今天仍然会处理这个应用程序,稍后我会检查这篇文章,特别是如果我因某种原因被卡住而谷歌无法帮助我。
【解决方案2】:

你可以像下面这样使用监督控制器模式

1 ) 定义接口 IView,ViewModel 将在其中使用所需的方法与 View 对话

public interface IView 
{
    void CreateDynamicWPFGrid();
}

2) 从 IView 继承 View 后面的代码并实现 IView.CreateDynamicWPFGrid() 方法

  public partial class View : IView 
{
    public void CreateDynamicWPFGrid() 
    {  
        // implement here your custom view logic using standard code behind; 
    }
}

3 ) 将 IView 类型的属性添加到您的 viewModel

    public class ViewModel 
{
    public IView View { get; set; }
}

4 ) 将 viewmodel 上的 View 属性设置为 IView 的 View 实例,例如在 DataContext.View = this as IView 后面的代码中;或者在 Caliburn 中你可以使用 IScreen.OnViewAttached 覆盖方法)

public View()
{

    (DataContext as ViewModel).View = this as IView;
} 

public void CreateDynamicWPFGrid() 
{  
    // implement here your custom view logic using standard code behind; 
}

5 ) 在您的视图模型中调用 IView.CreateDynamicWPFGrid()

    public class ViewModel 
{
    public IView View { get; set; }

    public void CreateDynamicWPFGrid() 
    {
        if (View == null)
        {
          return;
       } 
        View.CreateDynamicWPFGrid()
    }
}

【讨论】:

  • 虽然这是一种 MVVM 方法,但它只是推动了他的(部分不正确/不太正确)的方法,并试图使它们成为 MVVM-ish。相反,他应该做的是重组整个应用程序并从头开始,为他的数据构建适当的模型。
  • 同意卡米尔,虽然这在理论上可以解决我的问题并且是一个简单的解决方案。它不能正确解决我的 MVVM 结构问题,这是我正在处理/想知道的真正问题。不过还是谢谢 ;-)
猜你喜欢
  • 2013-10-21
  • 2010-12-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多