WPF MVVM

这篇具有很好参考价值的文章主要介绍了WPF MVVM。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

WPF MVVM

MVVM=Model+View+ViewModel

  • Model:现实世界中对象抽象的结果,也就是实体模型
  • View:UI界面
  • ViewModel:为UI界面服务的模型,可以理解为数据传输对象(DTO)
    ViewModel和View的沟通有两个方面:数据和操作
  • 传递数据–使用数据属性
  • 传递操作–使用命令属性
    很多人不理解MVVM和MVC的区别,我个人的理解是,MVC中的C可控范围更大,不仅可以控制View也能控制Model。而MVVM中,View是主动从ViewModel中获取数据,如果获取不到也不会导致程序崩溃,虽然VIewModel也可以去操作View,但是原则是View层主动获取数据,ViewModel是被动的提供数据。
    wpf viewmodel 数据传递,WPF,wpf,ui,c#,XAML,.net

案例1:

关注点:NotificationObject与数据属性
DelegateCommand与命令属性
wpf viewmodel 数据传递,WPF,wpf,ui,c#,XAML,.net

命令的传递(单向)

class DelegateCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        if (this.CanExecuteFunc == null)
        {
            return true;
        }

        return this.CanExecuteFunc(parameter);
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if (this.ExecuteAction == null)
        {
            return;
        }
        this.ExecuteAction(parameter);
    }

    public Action<object> ExecuteAction { get; set; }
    public Func<object, bool> CanExecuteFunc { get; set; }
}

ViewModels

//通知Binding属性更新,供ViewModels使用的类
class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
   
    public void RaisePropertyChanged(string propertyName)
    {
        //也可以这样声明,自动获取方法调用方的方法名称或属性名称
        //public void RaiseChanged([CallerMemberName]string proName=null)
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

该案例只有一个MainWindow,所以创建一个MainWindowViewModel类

class MainWindowViewModel : NotificationObject
{
    private double input1;

    public double Input1
    {
        get { return input1; }
        set
        {
            input1 = value;
            this.RaisePropertyChanged("Input1");
        }
    }

    private double input2;

    public double Input2
    {
        get { return input2; }
        set
        {
            input2 = value;
            this.RaisePropertyChanged("Input2");
        }
    }

    private double result;

    public double Result
    {
        get { return result; }
        set
        {
            result = value;
            this.RaisePropertyChanged("Result");
        }
    }

    public DelegateCommand AddCommand { get; set; }
    public DelegateCommand SaveCommand { get; set; }

    private void Add(object parameter)
    {
        this.Result = this.Input1 + this.Input2;
    }

    private void Save(object parameter)
    {
        SaveFileDialog dlg = new SaveFileDialog();
        dlg.ShowDialog();
    }

    public MainWindowViewModel()
    {
        this.AddCommand = new DelegateCommand();
        this.AddCommand.ExecuteAction = new Action<object>(this.Add);

        this.SaveCommand = new DelegateCommand();
        this.SaveCommand.ExecuteAction = new Action<object>(this.Save);
    }
}

主界面

<Window x:Class="SimpleMvvmDemo.Client.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Header="_Save" Command="{Binding SaveCommand}" />
            </MenuItem>
        </Menu>
        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Slider x:Name="slider1" Grid.Row="0" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4"  Value="{Binding Input1}" />
            <Slider x:Name="slider2" Grid.Row="1" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4"  Value="{Binding Input2}" />
            <Slider x:Name="slider3" Grid.Row="2" Background="LightBlue" Minimum="-100" Maximum="100" Margin="4" Value="{Binding Result}" />
            <Button x:Name="addButton" Grid.Row="3" Content="Add" Width="120" Height="80" Command="{Binding AddCommand}"/>
        </Grid>
    </Grid>
</Window>

由于Binding不指定Source默认使用了控件的DataContext,所以只需要在MainWindow中增加DataContext,子代控件便可以共享这个DataContext。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainWindowViewModel();
    }
}

案例2:

wpf viewmodel 数据传递,WPF,wpf,ui,c#,XAML,.net

项目使用了Microsoft.Practices.Prism,需要提前引用

  • Models

要显示单品和饭店信息,所以定义Dish和Restaurant两个类

public class Dish : NotificationObject
{
    public string Name { get; set; }
    public string Category { get; set; }
    public string Comment { get; set; }
    public double Score { get; set; }
}
class Restaurant : NotificationObject
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}
  • Services

具有获得菜单和点单服务,先定义相关接口,再实现类

public interface IDataService
{
    List<Dish> GetAllDishes();
}
class XmlDataService : IDataService
{
    public List<Dish> GetAllDishes()
    {
        List<Dish> dishList = new List<Dish>();
        string xmlFileName = System.IO.Path.Combine(Environment.CurrentDirectory, @"Data\Data.xml");
        XDocument xDoc = XDocument.Load(xmlFileName);
        var dishes = xDoc.Descendants("Dish");
        foreach (var d in dishes)
        {
            Dish dish = new Dish();
            dish.Name = d.Element("Name").Value;
            dish.Category = d.Element("Category").Value;
            dish.Comment = d.Element("Comment").Value;
            dish.Score = double.Parse(d.Element("Score").Value);
            dishList.Add(dish);
        }

        return dishList;
    }
}
interface IOrderService
{
    void PlaceOrder(List<string> dishes);
}
class MockOrderService : IOrderService
{
    public void PlaceOrder(List<string> dishes)
    {
        System.IO.File.WriteAllLines(@"C:\Users\cni23287938\Desktop\orders.txt", dishes.ToArray());
    }
}
  • ViewModels

因为菜单后面需要具有一个是否选择项,所以要新定义一个DishMenuItemViewModel类

class DishMenuItemViewModel : NotificationObject
{
    public Dish Dish { get; set; }

    private bool isSelected;

    public bool IsSelected
    {
        get { return isSelected; }
        set
        {
            isSelected = value;
            this.RaisePropertyChanged("IsSelected");
        }
    }
}

MainWindowViewModel

class MainWindowViewModel : NotificationObject
{
    private int count;

    public int Count
    {
        get { return count; }
        set { count = value; this.RaisePropertyChanged("Count"); }
    }

    private Restaurant restaurant;

    public Restaurant Restaurant
    {
        get { return restaurant; }
        set { restaurant = value; this.RaisePropertyChanged("restaurant"); }
    }
    private List<DishMenuItemViewModel> dishMenu;

    public List<DishMenuItemViewModel> DishMenu
    {
        get { return dishMenu; }
        set { dishMenu = value; this.RaisePropertyChanged("DishMenu"); }
    }
    public DelegateCommand PlaceOrderCommand { get; set; }
    public DelegateCommand SelectMenuItemCommand { get; set; }


    public MainWindowViewModel()
    {
        LoadRestaurant();
        LoadDishMenu();
        PlaceOrderCommand = new DelegateCommand(this.PlaceOrderCommandExecute);
        SelectMenuItemCommand = new DelegateCommand(this.SelectMenuItemExecute);
    }


    private void LoadRestaurant()
    {
        this.Restaurant = new Restaurant();
        this.Restaurant.Name = "Crazy";
        this.restaurant.Address = "北京";
        this.restaurant.PhoneNumber = "1";
    }

    private void LoadDishMenu()
    {
        IDataService ds = new XmlDataService();
        var dishes = ds.GetAllDishes();
        this.dishMenu = new List<DishMenuItemViewModel>();
        foreach (var dish in dishes)
        {
            DishMenuItemViewModel item = new DishMenuItemViewModel();
            item.Dish = dish;
            this.dishMenu.Add(item);
        }
    }
    private void PlaceOrderCommandExecute()
    {
        var selectedDishes = this.dishMenu.Where(i => i.IsSelected == true).Select(i => i.Dish.Name).ToList();
        IOrderService orderService = new MockOrderService();
        orderService.PlaceOrder(selectedDishes);
        MessageBox.Show("订餐成功");
    }
    private void SelectMenuItemExecute()
    {
        Count = DishMenu.Count(i => i.IsSelected == true);
    }
}

xaml文章来源地址https://www.toymoban.com/news/detail-603473.html

<Window x:Class="WpfApp8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp8"
        mc:Ignorable="d"
        Title="{Binding Restaurant.Name}" Height="600" Width="800" WindowStartupLocation="CenterScreen">

    <Grid x:Name="Root" Margin="4">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="欢迎"/>
                <TextBlock Text="{Binding Restaurant.Name}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="电话"/>
                <TextBlock Text="{Binding Restaurant.PhoneNumber}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="地址"/>
                <TextBlock Text="{Binding Restaurant.Address}"/>
            </StackPanel>
        </StackPanel>
        <DataGrid AutoGenerateColumns="False" CanUserDeleteRows="False" CanUserAddRows="False" Grid.Row="1" ItemsSource="{Binding DishMenu}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="菜品" Binding="{Binding Dish.Name}" Width="120"/>
                <DataGridTextColumn Header="种类" Binding="{Binding Dish.Category}" Width="120"/>
                <DataGridTextColumn Header="点评" Binding="{Binding Dish.Comment}" Width="120"/>
                <DataGridTextColumn Header="推荐分数" Binding="{Binding Dish.Score}" Width="120"/>
                <DataGridTemplateColumn Header="选中" SortMemberPath="IsSelected" Width="120">
                    <DataGridTemplateColumn.CellTemplate>
                        <!--要获取每列数据,为每条数据赋值Command-->
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding Path=IsSelected,UpdateSourceTrigger=PropertyChanged}" Command="{Binding Path=DataContext.SelectMenuItemCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Grid.Row="2">
            <TextBlock Text="共计:"/>
            <TextBox IsReadOnly="True" Text="{Binding Count}"/>
            <Button Content="Order" Command="{Binding PlaceOrderCommand}"/>
        </StackPanel>
    </Grid>
</Window>

到了这里,关于WPF MVVM的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【WPF系列】- XAML语法规范

    定义XAML语法术语是XAML语言规范中进行定义或引用。XAML是基于XML的语言,遵循或扩展XML结构规则。XAML是基于描述XML语言或XML文档对象模型时常用的术语。 XAML是一种标记语言。CLR是可实现运行时语言。XAML不是CRL运行一部分。仅是使用于WPF的XAML时实例化运行的一种表达形式。

    2024年02月05日
    浏览(35)
  • WPF: XAML语法规范详解

    WPF(Windows Presentation Foundation)是.NET框架的一个组成部分,用于构建桌面应用程序的用户界面。XAML(Extensible Application Markup Language)是一种基于XML的标记语言,用于定义WPF应用程序的界面和逻辑。 XAML文件扩展名为.xaml,它是一种XML格式的文件。XAML文件通常包含以下部分: x

    2024年04月23日
    浏览(25)
  • 【wpf】xaml 中的参数复用

    xaml中有几种复用的方式: 有时在xaml中,我们需要复用一些参数,比如 固定的一个值。 有时是固定的一个样式。 有时多个控件都要设置一个高度,我可以引入sys 我就使用这个吧: xmlns:sys=\\\"clr-namespace:System;assembly=mscorlib\\\" 用的更多的其实是margin,我们试一试: 这里 mm 用的是

    2024年02月07日
    浏览(67)
  • WPF XAML中使用依赖属性

    自定义的控件 MyCustomControl ,它有一个依赖属性 MyProperty 。首先,我们需要在控件的代码文件中创建这个依赖属性: 在XAML文件中使用这个控件及其依赖属性: 在这个例子中, local 是XAML文件中定义的XML命名空间前缀, clr-namespace:WpfApp 指定了 MyCustomControl 定义所在的命名空间。

    2024年02月20日
    浏览(31)
  • Microsoft.Xaml.Behaviors.Wpf 的使用

    System.Windows.Interactivity.WPF这个已经过时,可以使用 Microsoft.Xaml.Behaviors.Wpf ,基本使用查不多,

    2024年02月13日
    浏览(37)
  • c#WPF 自定义UI控件学习,vb.net界面UI美化

    最近项目中运用到了WPF处理三维软件,在C/S结构中WPF做UI还是有很多优越性,简单的学了一点WPF知识,成功的完成项目目标。项目过度阶段对于WPF的一些基本特点有了进一步了解 。至此花费一点时间研究研究WPF控件。 为以后的项目开发中提供一些可观的资源也是不错的。 目

    2024年02月20日
    浏览(38)
  • 二、深入浅出WPF之系统学习XAML语法

    跟Winforms一样,UI也是个平面结构,与winforms的设计思维不同,WPF使用树形逻辑来描述UI,下面是UI布局的简单代码 实际的页面效果:

    2024年02月16日
    浏览(34)
  • WPF国际化的实现方法(WpfExtensions.Xaml)

    https://blog.csdn.net/eyupaopao/article/details/120090431 resx资源文件实现 resx资源文件,实现的过程比第一种复杂,但resx文件本身编辑比较简单,维护起来比较方便。需要用到的框架:WpfExtensions.Xaml 为每种语言添加.resx资源文件,放在I18nResource文件夹下 I18nResource.resx 代表英语,名字不要

    2024年02月12日
    浏览(24)
  • WPF绘图指南:用XAML轻松实现圆、线、矩形、文字、图片创意元素

      概述: 在WPF中,通过使用不同的元素如Ellipse、Line、Rectangle等,可以轻松绘制各种图形,包括圆、线条、椭圆、矩形、多边形等。同时,通过TextBlock展示文字,Image展示图片,以及Path创建路径和曲线,使得图形的绘制变得灵活多样。通过简单的XAML代码,开发者可以快速构建

    2024年03月13日
    浏览(34)
  • WPF实现更加灵活绑定复杂Command(使用Microsoft XAML Behaviors 库)

    1、安装NuGet          2、在XAML的命名空间引入: 3、使用(这里是设置了一个Canvas的点击事件,其它面板也是类似这样设置):         --我这里的ViewModel部分是这样子的 4、这样就可以在ViewModel中直接给这个Command内容了,不用像之前那么麻烦地绑定Command了,这样更加清晰,

    2024年02月04日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包