首页 > 解决方案 > c# WPF 需要帮助:如何通过 WPF 显示对象中的值

问题描述

[2019-02-23编辑;我希望编辑问题是正确的]

我是 WPF 的新手,并且正在苦苦挣扎。我看过很多教程等,但没有找到答案(以我理解的方式)。

我正在构建一个 Yatzy 游戏,它自己的 Yatzy 类几乎完成了。现在我想在 yatzy 类中添加一个使用 WPF 的 GUI。

感谢 Reginald Blue 回答我的问题 v1 的意见。我正在研究视图模型。

Mark Whitall 做了一个很好的例子,但我无法将它迁移到我的需要:

但这也让我很困扰。我希望提供的代码是足够的,如果不是 - 问:-)

它看起来像我的视图模型,与我的模型有“联系”。那是超级但是关于我的视图连接到我的视图模型,似乎有问题。

作为开始,我想做什么:1)当字段 GameStatus 和 GameName 应该具有我的模型的默认值时。在制作我的视图模型之前,它工作得很好——但我把它搞砸了。我在 maincontrol.cs(在视图模型中)声明了我的 thisYatzy 对象。我应该在 app.xaml 级别声明它吗?2)当我点击“按钮”ShiftState时,我会调用我的视图模型来改变状态,并更新视图。但是从视图中我不能调用视图模型?

我希望我已经解释好了,你们中的某个人可以提供帮助:-)

看法:

应用程序.xalm

<Application x:Class="WPFYatzy.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WPFYatzy"
             StartupUri="Views/MainWindow.xaml">
    <Application.Resources>

    </Application.Resources>
</Application>

应用程序.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFYatzy.Views
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
                 }
    }
}

主窗口.xaml

<Window x:Class="MinimalMVVM.Views.ConvertWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Views="clr-namespace:WPFYatzy.Views"
        xmlns:ViewModels="clr-namespace:WPFYatzy.ViewModel"
        Title="YatzyGame - mainwindow"
        MinWidth="300"
        ResizeMode="NoResize"
        SizeToContent="WidthAndHeight">

    <Window.DataContext>
        <ViewModels:MainControl/>
    </Window.DataContext>

    <Views:Page1/>

</Window>

主窗口.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using YatzyGameCL;

namespace WPFYatzy
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //YatzyGame thisYatzy = new YatzyGame();

        public MainWindow()
        {
            //InitializeComponent();
        }

        private void OnInit(object sender, EventArgs e)
        {

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

        }
    }

}

page1.xaml

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFYatzy.Views
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
                 }
    }
}

page1.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFYatzy.Views
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
                 }
    }
}

视图模型

ObservableObject.cs

using System.ComponentModel;

namespace WPFYatzy.ViewModel
{
    public abstract class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChangedEvent(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

委托命令.cs

using System;
using System.Windows.Input;

namespace WPFYatzy.ViewModel
{
    public class DelegateCommand : ICommand
    {
        private readonly Action _action;

        public DelegateCommand(Action action)
        {
            _action = action;
        }

        public void Execute(object parameter)
        {
            _action();
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

#pragma warning disable 67
        public event EventHandler CanExecuteChanged { add { } remove { } }
#pragma warning restore 67
    }
}

主控件.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using YatzyGameCL;

namespace WPFYatzy.ViewModel
{
    class MainControl : ObservableObject
    {
        private YatzyGame thisYatzy = new YatzyGame();

        private string _strGameName;
        private string _strGameStatus;

        public string GameName
        {
            get { return _strGameName; }
            set
            {
                _strGameName = value;
                RaisePropertyChangedEvent("GameName");
            }

        }

        public string GameStatus
        {
            get { return _strGameStatus; }
            set {
                _strGameStatus = value;
                RaisePropertyChangedEvent("GameStatus");
            }
        }

        public void ShiftState()
        {
            thisYatzy.GameStatus.NextAround();

            GameStatus = thisYatzy.GameStatus.ToString();

        }
    }
}

模型 YatzyGameCL.DLL

用于使框架“挂在一起”的方法

标签: c#wpf

解决方案


这将很难简洁地表达。你应该去阅读 MVVM (Model-View-ViewModel) 模式。虽然将 MVVM 与 WPF 一起使用并不是绝对必要的,但对于您正在做的事情,它确实是您需要的地方。

具体来说:

您创建了一个模型。那是你的 YatzyGame。它知道 Yatzy 是如何工作的,拥有所有规则。这就是“游戏”。

你有一个观点。那是您的 XAML 文件(以及背后的代码)。它知道如何绘制屏幕,​​并且知道如何在被告知时进行更新。

但是……你没有 ViewModel。那是两个世界之间的桥梁。它知道如何告诉视图更新。您的模型不(也不应该)知道如何做到这一点,因此视图(屏幕)永远不会改变。

您的问题的非常具体的答案是您需要发送属性更改通知,以便视图知道属性(例如 GameStatus)已更改。你会很想在你的模型中这样做。不要那样做。

祝你好运!


推荐阅读