最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解WPF中MVVM架構(gòu)中的多種數(shù)據(jù)綁定方式

 更新時(shí)間:2025年09月26日 09:41:41   作者:苦蕎米  
這篇文章主要為大家詳細(xì)介紹了WPF中MVVM架構(gòu)中的多種數(shù)據(jù)綁定方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

WPF基礎(chǔ)框架

通過繼承接口INotifyPropertyChangedICommand 來實(shí)現(xiàn)。

數(shù)據(jù)綁定部分

INotifyPropertyChanged原代碼如下,WPF框架會(huì)自動(dòng)注冊(cè)DataContext對(duì)象中的PropertyChanged事件(若事件存在)。然后根據(jù)該事件修改前端屬性。

namespace System.ComponentModel
{
    // Notifies clients that a property value has changed.
    public interface INotifyPropertyChanged
    {
        // Occurs when a property value changes.
        event PropertyChangedEventHandler? PropertyChanged;
    }
}

注意:INotifyPropertyChanged接口并非是強(qiáng)制要求的,當(dāng)不需要通過設(shè)置屬性自動(dòng)修改頁(yè)面數(shù)據(jù)時(shí),也就是不需要執(zhí)行set方法時(shí),不需要繼承該接口。若使用了通知集合ObservableCollection,也是不需要專門通過事件通知頁(yè)面的。

public class NativeViewModel : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged();
            }
        }
    }
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
<StackPanel>
    <TextBox Text="{Binding Name}" />
</StackPanel>

數(shù)據(jù)綁定中的命令綁定

ICommand 原代碼如下,可以看到其中有按鈕操作常用的幾種屬性:是否可用、可用性變化、觸發(fā)事件。與前端通過Click屬性指定事件相比:一個(gè)是前端指定要執(zhí)行的邏輯,一個(gè)是由vm來確定最終的執(zhí)行邏輯,相當(dāng)于是反轉(zhuǎn)了控制方??梢愿鶕?jù)需要使用、并非強(qiáng)制要求。

#nullable enable

using System.ComponentModel;
using System.Windows.Markup;

namespace System.Windows.Input
{
    //
    // 摘要:
    //     Defines a command.
    [TypeConverter("System.Windows.Input.CommandConverter, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
    [ValueSerializer("System.Windows.Input.CommandValueSerializer, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
    public interface ICommand
    {
        //
        // 摘要:
        //     Occurs when changes occur that affect whether or not the command should execute.
        event EventHandler? CanExecuteChanged;

        //
        // 摘要:
        //     Defines the method that determines whether the command can execute in its current
        //     state.
        //
        // 參數(shù):
        //   parameter:
        //     Data used by the command. If the command does not require data to be passed,
        //     this object can be set to null.
        //
        // 返回結(jié)果:
        //     true if this command can be executed; otherwise, false.
        bool CanExecute(object? parameter);
        //
        // 摘要:
        //     Defines the method to be called when the command is invoked.
        //
        // 參數(shù):
        //   parameter:
        //     Data used by the command. If the command does not require data to be passed,
        //     this object can be set to null.
        void Execute(object? parameter);
    }
}

對(duì)于ICommand屬性,推薦使用方式是不要讓其觸發(fā)PropertyChanged,不應(yīng)該被動(dòng)態(tài)設(shè)置,而應(yīng)該初始定好。不過如果使用場(chǎng)景確實(shí)需要,應(yīng)該也是能生效的。

public class NativeViewModel
{
    public ICommand GreetCommand { get; }

    public NativeViewModel()
    {
        // 使用自定義的 RelayCommand 需要自己實(shí)現(xiàn)
        GreetCommand = new RelayCommand();
    }
}

// 需要實(shí)現(xiàn)的簡(jiǎn)單命令類
public class RelayCommand : ICommand
{
    // 略
}
<StackPanel>
    <Button Content="Say Hello" Command="{Binding GreetCommand}" />
</StackPanel>

CommunityToolkit.Mvvm 方式

CommunityToolkit.Mvvm 利用 C# 的源碼生成器,在編譯時(shí)自動(dòng)生成INotifyPropertyChangedICommand的樣板代碼。需要nuget包CommunityToolkit.Mvvm。

其僅在vm上有區(qū)別,在實(shí)際綁定方式上沒有區(qū)別。

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

// 3. 使用 [ObservableObject] 特性或繼承 ObservableObject
[ObservableObject]
public partial class ToolkitViewModel
{
    // 4. 使用 [ObservableProperty] 標(biāo)記字段,自動(dòng)生成名為 "Name" 的屬性
    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(GreetCommand))] // 當(dāng) Name 改變時(shí),通知 GreetCommand 重新驗(yàn)證
    private string _name;

    [ObservableProperty]
    private string _greeting;

    // 5. 使用 [RelayCommand] 自動(dòng)生成名為 GreetCommand 的 ICommand 屬性
    [RelayCommand(CanExecute = nameof(CanGreet))]
    private void Greet()
    {
        Greeting = $"Hello from Toolkit, {Name}!";
    }

    private bool CanGreet() => !string.IsNullOrWhiteSpace(Name);
}

ReactiveUI

ReactiveUI 將響應(yīng)式編程理念引入 MVVM,核心是使用ReactiveObjectWhenAnyValue等來聲明數(shù)據(jù)流和反應(yīng)關(guān)系。需要nuget包ReactiveUI.WPF

其僅在vm上有區(qū)別,在實(shí)際綁定方式上沒有區(qū)別。

using ReactiveUI;
using System.Reactive.Linq;

// 6. 繼承 ReactiveObject
public class ReactiveViewModel : ReactiveObject
{
    // 7. 使用 [Reactive] 特性或 WhenAnyValue
    private string _name;
    public string Name
    {
        get => _name;
        set => this.RaiseAndSetIfChanged(ref _name, value);
    }

    private readonly ObservableAsPropertyHelper<string> _greeting;
    public string Greeting => _greeting.Value;

    // 8. 使用 ReactiveCommand 創(chuàng)建命令
    public ReactiveCommand<Unit, Unit> GreetCommand { get; }

    public ReactiveViewModel()
    {
        // 判斷命令何時(shí)可執(zhí)行:當(dāng) Name 不為空時(shí)
        var canGreet = this.WhenAnyValue(x => x.Name, name => !string.IsNullOrWhiteSpace(name));

        // 創(chuàng)建命令
        GreetCommand = ReactiveCommand.CreateFromTask(
            execute: async () => { /* 可以執(zhí)行異步操作 */ return $"Hello from ReactiveUI, {Name}!"; },
            canExecute: canGreet // 綁定可執(zhí)行條件
        );

        // 9. 將命令的執(zhí)行結(jié)果(一個(gè)IObservable<string>)訂閱到 Greeting 屬性
        _greeting = GreetCommand.ToProperty(this, x => x.Greeting, initialValue: "Waiting...");

        // 另一種更直接的寫法(不通過命令結(jié)果):
        // GreetCommand = ReactiveCommand.Create(() => { Greeting = $"Hello from ReactiveUI, {Name}!"; }, canGreet);
        // 但上面那種方式展示了將 IObservable 流轉(zhuǎn)換為屬性的強(qiáng)大能力。
    }
}

到此這篇關(guān)于詳解WPF中MVVM架構(gòu)中的多種數(shù)據(jù)綁定方式的文章就介紹到這了,更多相關(guān)WPF MVVM架構(gòu)的數(shù)據(jù)綁定內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c#:CTS類型系統(tǒng)

    c#:CTS類型系統(tǒng)

    CTS通用類型系統(tǒng),是.Net中一套定義類型的規(guī)則。我們要掌握c#開發(fā),首先要建立這個(gè)類型概念,只有知道c#的元素是什么類型,才能進(jìn)行相關(guān)的分析和選材。
    2012-12-12
  • C#零基礎(chǔ)開發(fā)中最重要的概念總結(jié)

    C#零基礎(chǔ)開發(fā)中最重要的概念總結(jié)

    這篇文章主要為大家詳細(xì)介紹了C#零基礎(chǔ)開發(fā)中最重要的一些概念,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,需要的可以參考一下
    2023-02-02
  • C#中常使用進(jìn)度條的代碼

    C#中常使用進(jìn)度條的代碼

    C#中常使用進(jìn)度條的代碼...
    2007-03-03
  • 基于C#實(shí)現(xiàn)獲取本地磁盤目錄

    基于C#實(shí)現(xiàn)獲取本地磁盤目錄

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)獲取本地磁盤目錄的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • C#從foreach語(yǔ)句中枚舉元素看數(shù)組詳解

    C#從foreach語(yǔ)句中枚舉元素看數(shù)組詳解

    這篇文章主要給大家介紹了關(guān)于C#從foreach語(yǔ)句中枚舉元素看數(shù)組的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • WPF中引入WindowsForms控件的方法

    WPF中引入WindowsForms控件的方法

    這篇文章主要介紹了WPF中引入WindowsForms控件的方法,結(jié)合實(shí)例形式分析了在WPF中調(diào)用Windows Forms控件的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-07-07
  • C#凈化版WebApi框架的實(shí)現(xiàn)

    C#凈化版WebApi框架的實(shí)現(xiàn)

    這篇文章主要介紹了C#凈化版WebApi框架的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • C#特性-對(duì)象集合初始化器介紹

    C#特性-對(duì)象集合初始化器介紹

    在寫一些實(shí)體類的時(shí)候,我們往往在寫構(gòu)造方法的時(shí)候思考很長(zhǎng)時(shí)間,除了一個(gè)無(wú)參構(gòu)造器外還在想需要寫幾個(gè)構(gòu)造器呢?哪些參數(shù)是需要初始化的?,F(xiàn)在你再也不需要為這事煩惱了
    2014-12-12
  • c#斐波那契數(shù)列(Fibonacci)(遞歸,非遞歸)實(shí)現(xiàn)代碼

    c#斐波那契數(shù)列(Fibonacci)(遞歸,非遞歸)實(shí)現(xiàn)代碼

    c#斐波那契數(shù)列(Fibonacci)(遞歸,非遞歸)實(shí)現(xiàn)代碼,需要的朋友可以參考一下
    2013-05-05
  • C#制作二維柱狀圖方法

    C#制作二維柱狀圖方法

    在本文里小編為各位分享的是關(guān)于C#制作二維柱狀圖方法和步驟,需要的讀者們學(xué)習(xí)下。
    2018-12-12

最新評(píng)論

灯塔市| 卓资县| 綦江县| 嘉兴市| 舒兰市| 凤冈县| 凤山市| 灵石县| 新宾| 沐川县| 克拉玛依市| 瑞丽市| 兖州市| 平南县| 尼勒克县| 江都市| 含山县| 吐鲁番市| 锡林郭勒盟| 页游| 青神县| 通山县| 宣恩县| 昌黎县| 湄潭县| 平阳县| 秀山| 连南| 隆回县| 平乡县| 绥化市| 久治县| 江口县| 菏泽市| 东乡族自治县| 安化县| 循化| 蒙山县| 中牟县| 安泽县| 扎兰屯市|