《WPF》--DataContext数据双向绑定

本文介绍了WPF中数据绑定的概念,包括前端和后台设置DataContext的方法,以及数据双向绑定的最佳实践。接着,文章讨论了Fody库在解决数据变化不更新视图问题中的作用,并提供了安装和配置教程。最后,通过一个移动方块的案例,展示了如何结合数据绑定和键盘事件实现动态交互效果。


提示:以下是本篇文章正文内容,下面案例可供参考

一、数据绑定

1)在FrameworkElement类下有两个重要的属性。

  • Resources:获取或设置本地定义的资源字典。
  • DataContext:获取或设置元素参与数据绑定时的数据上下文。

利用这两个属性,可以实现UI数据直接与后台的类进行绑定

2)前端UI界面属性值等动态与后台绑定的方式有多种,此处列出后台设置DataContext以及前端设置DataContext的两种方式,以及数据双向绑定的最佳实践

前端设置DataContext

纯前端的方式好处在于,编译一下,就可以在设计阶段看到效果。
1)先定义好我们的类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2.entity
{
    public class MyButtton
    {
        public string color { get; set; } = "Red";
    }
}

2)在前端按照步骤引入

<Window x:Class="WpfApp2.login"
        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:WpfApp2"
        xmlns:btn="clr-namespace:WpfApp2.entity"
        mc:Ignorable="d"
        Title="登录页" Height="450" Width="800"
        >
    <Grid Name="g">
        <!-- 1.声明资源位置 xmlns:btn="clr-namespace:WpfApp2.entity" -->
        <!-- 2.绑定类资源,key是别名,value是类 -->
        <Grid.Resources>
            <btn:MyButtton x:Key="myDatasource"/>
        </Grid.Resources>
        
        <!-- 3.将绑定的资源加入到当前上下文(加入后即可使用) -->
        <Grid.DataContext>
            <Binding Source="{StaticResource myDatasource}"/>   
        </Grid.DataContext>
        
        <!-- 4.使用属性,直接使用类的属性名即可 -->
        <Button Background="{Binding Path=color}" Width="100" Height="50" Click="Button_Click_1">按钮</Button>

    </Grid>
</Window>

后台设置DataContext

在设计阶段是看不到效果的,但是灵活性更高,属性值不用写死
1)定义一个类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2.entity
{
    public class Mytitle
    {
        public string Title { get; set; }
        public string color { get; set; }
    }
}

2)在当前窗口加载时,进行绑定DataContext

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    this.DataContext = new Mytitle() 
    {
        t="我是标题",
        color="Red"
    };
}

3)前端

<Window x:Class="WpfApp2.login"
        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:WpfApp2"
        d:DesignHeight="450" d:DesignWidth="800"
        Loaded="Window_Loaded"
        mc:Ignorable="d"
        >
    <Grid>
        <Label Content="{Binding Path=t}"></Label>
    </Grid>
</Window>

二、Fody

在应用中,会很快发现一个问题,数据绑定只有一次,后续我们的数据变化,并不会引起我们视图的变化,这时候需要引入一个轮子,那就是Fody。Fody包会自动将数据和绑定的UI进行同步刷新,来达到我们的要求

安装

1)引入下面三个包
在这里插入图片描述
2)添加FodyWeavers.xml文件
在这里插入图片描述
配置信息如下:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <PropertyChanged />
</Weavers>

如果显示已经存在此文件,则从文件夹打开当前项目,显示的复制到项目里,将配置文件添加到xml中。

测试

设置一个简单布局,通过点击按钮,来使得label中数字递增
在这里插入图片描述
1)创建一个类,继承INotifyPropertyChanged,并且alt+enter进行快速实现即可

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp3.src
{
    public class Number: INotifyPropertyChanged
    {
        public int num { get;set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

2)在loaded事件中,添加到DataContext中,在按钮事件中进行++操作

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 WpfApp3.src;

namespace WpfApp3
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private static Number number = new Number()
        {
            num = 0,
        };

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = number;
        }

        private void addd(object sender, RoutedEventArgs e)
        {
            number.num++;
        }
    }

}

3)前端UI直接使用Binding进行绑定

<Window x:Class="WpfApp3.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:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Loaded="Window_Loaded"
        >
    <Grid>
        <Label VerticalAlignment="Top" HorizontalAlignment="Left" Width="100" Height="50" Background="Red"
               Content="{Binding Path=num}"></Label>
        <Button Content="button" Width="100" Height="100" Background="Gray" Click="addd"></Button>
    </Grid>
</Window>

三、案例

移动方块

需求:一个白色的方块,通过上下左右键进行操控方块的移动,到达顶部后自动回到当前行或列的起点。
在这里插入图片描述
1)编写数据绑定类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp3.src
{
    public class Number: INotifyPropertyChanged
    {
        public int num { get;set; }//用不到这个
        public int rowNum { get;set; }
        public int colNum { get;set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

2)页面布局和设置响应事件,千万注意:窗口默认不支持keydown,要开启可焦点功能,然后在窗体初始化时,进行当前窗体的直接聚焦。

<Page x:Class="WpfApp3.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfApp3"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Loaded="Page_Loaded"  
      Title="Page1" KeyDown="Grid_KeyDown" Focusable="True">

    <Grid ShowGridLines="True" Background="Green">
        <Grid.ColumnDefinitions>
            <ColumnDefinition>
            </ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Border Grid.Row="{Binding Path=rowNum}" Grid.Column="{Binding Path=colNum}" Background="White"></Border>
    </Grid>
</Page>

3)后台

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 WpfApp3.src;

namespace WpfApp3
{
    /// <summary>
    /// Page1.xaml 的交互逻辑
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }

        private static Number num = new Number()
        {
            rowNum = 0,
            colNum = 0,
        };

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = num;
            this.Focus();
        }

        private void Grid_KeyDown(object sender, KeyEventArgs e)
        {
            //MessageBox.Show(e.Key.ToString());
            //num.rowNum++;
            switch (e.Key)
            {
                case Key.Left:
                    num.colNum = (num.colNum +2)%3;
                    break;
                case Key.Right:
                    num.colNum = (num.colNum +1)%3;
                    break;
                case Key.Up:
                    num.rowNum = (num.rowNum +2)%3;
                    break;
                case Key.Down:
                    num.rowNum = (num.rowNum +1)%3;
                    break;
                default:
                    break;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值