CommunityToolkit.Mvvm详解

发布于:2025-05-10 ⋅ 阅读:(12) ⋅ 点赞:(0)

属性可视化

给一个属性添加ObservableProperty就可以可视化了

[ObservableProperty]
private string currentNameInfo;

[ObservableProperty]
private string currentClassInfo;

[ObservableProperty]
private string currentPhoneInfo;

xaml中只需要绑定大写的属性就可以了

<StackPanel Orientation="Horizontal"
            Grid.ColumnSpan="2"
            Grid.Row="1">
    <TextBlock 
               Width="200"
               Height="40"
               FontSize="30"
               Text="{Binding CurrentNameInfo,TargetNullValue=null}"
               HorizontalAlignment="Center" />
    <TextBlock 
               Width="200"
               Height="40"
               FontSize="30"
               Text="{Binding CurrentClassInfo,TargetNullValue=null}"
               HorizontalAlignment="Center" />
    <TextBlock Grid.Row="1"
               Width="200"
               Height="40"
               FontSize="30"
               Text="{Binding CurrentPhoneInfo,TargetNullValue=null}"
               HorizontalAlignment="Center" />
</StackPanel>

命令

可以用RelayCommand来简便的指定命令

[RelayCommand]
void AddButtonClick()
{
    Student student = new Student(NameProperty, ClassProperty, PhoneProperty);
    WeakReferenceMessenger.Default.Send(new ValueChangedMessage<Student>(student));
}

xaml中只需要绑定方法名加Command就可以了

<Button Grid.Row="3"
        Content="存入列表"
        Height="40"
        IsEnabled="{Binding CanAllow}"
        Command="{Binding AddButtonClickCommand}"
        Width="100" />

Message

传递自定义类

两个ViewModel之间传递自定义类

1.定义一个自定义的类

public record StringMessage(string message);

2.注册自定义类

通过WeakReferenceMessenger来注册StringMessage

public partial class ReciverUCViewModel:ObservableObject
{

    [ObservableProperty]
    private string? recivetxt;

    public ReciverUCViewModel()
    {
        WeakReferenceMessenger.Default.Register<StringMessage>(this, Receive);
    }

    private void Receive(object recipient, StringMessage message)
    {
        Recivetxt = message.message;
    }
}

3.发送消息

public partial class SenderUCViewModel : ObservableObject
{
    //[ObservableProperty]
    //private string? sendertxt="null";

    private string? sendertxt;

    public string Sendertxt
    {
        get { return sendertxt; }
        set
        {
            if (SetProperty(ref sendertxt, value))
            {
                WeakReferenceMessenger.Default.Send(new StringMessage(value));
            }
        }

    }
}

传递PropertyChangedMessage

接收

public partial class ReciverUCViewModel:ObservableObject
{

    [ObservableProperty]
    private string? recivetxt;

    public ReciverUCViewModel()
    {
        WeakReferenceMessenger.Default.Register<PropertyChangedMessage<string>>(this,Receive);
    }

    private void Receive(object recipient, PropertyChangedMessage<string> message)
    {
        Recivetxt = message.NewValue;
    }
}

可以用IRecipient来优化简便代码

public partial class ReciverUCViewModel : ObservableObject, IRecipient<PropertyChangedMessage<string>>
{

    [ObservableProperty]
    private string? recivetxt;

    public ReciverUCViewModel()
    {
        WeakReferenceMessenger.Default.Register(this);
    }

    public void Receive(PropertyChangedMessage<string> message)
    {
        Recivetxt = message.NewValue;
    }
}

发送

public partial class SenderUCViewModel : ObservableObject
{
    //[ObservableProperty]
    //private string? sendertxt="null";

    private string? sendertxt;

    public string Sendertxt
    {
        get { return sendertxt; }
        set
        {
            if (SetProperty(ref sendertxt, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this,nameof(Sendertxt),default,value));
            }
        }

    }
}

传递RequestMessage

发送

public partial class SenderUCViewModel : ObservableObject
{
    //[ObservableProperty]
    //private string? sendertxt="null";

    private string? sendertxt;

    public string Sendertxt
    {
        get { return sendertxt; }
        set
        {
            if (SetProperty(ref sendertxt, value))
            {
                var res=WeakReferenceMessenger.Default.Send(new RequestMessage<string>());
                sendertxt = res.Response;
            }
        }

    }
}

接收

public partial class ReciverUCViewModel : ObservableObject,IRecipient<RequestMessage<string>>
{

    [ObservableProperty]
    private string? recivetxt;

    public ReciverUCViewModel()
    {
        WeakReferenceMessenger.Default.Register(this);
    }

    public void Receive(RequestMessage<string> message)
    {
        recivetxt = message.ToString();
        message.Reply("hello");
    }

 
}

简化

ObservableRecipient

可以替代ObservableObject,还能简化注册功能,设置属性IsActive=true就可以免注册

IRecipient

可以直接指明,要接收的类型

public partial class ReciverUCViewModel : ObservableRecipient,IRecipient<PropertyChangedMessage<string>>
{

    [ObservableProperty]
    private string? recivetxt;

    
    public ReciverUCViewModel()
    {
        //WeakReferenceMessenger.Default.Register(this);
        this.IsActive = true;
    }

    public void Receive(PropertyChangedMessage<string> message)
    {
        Recivetxt = message.NewValue;
    }
}

心得

对于发送的相同类型的message,可以通过属性的名称来区分,分别处理

发送

public partial class FormUCViewModel:ObservableRecipient
{
    private string nameProperty;

    public string NameProperty
    {
        get { return nameProperty; }
        set {
            if (SetProperty(ref nameProperty, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this, nameof(NameProperty), default, value));
            }
        }
    }

    private string classProperty;

    public string ClassProperty
    {
        get { return classProperty; }
        set {
            if (SetProperty(ref classProperty, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this, nameof(ClassProperty), default, value));
            }
        }
    }

    private string phoneProperty;

    public string PhoneProperty
    {
        get { return phoneProperty; }
        set {
            if (SetProperty(ref phoneProperty, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this, nameof(PhoneProperty), default, value));
            }
        }
    }


}

接收

public partial class MainWindowViewModel:ObservableRecipient,IRecipient<PropertyChangedMessage<string>>
{
    [ObservableProperty]
    private string currentNameInfo;

    [ObservableProperty]
    private string currentClassInfo;

    [ObservableProperty]
    private string currentPhoneInfo;

    public MainWindowViewModel()
    {
        this.IsActive = true;
    }

    public void Receive(PropertyChangedMessage<string> message)
    {
        // 根据消息的属性名称更新相应的属性
        switch (message.PropertyName)
        {
            case nameof(FormUCViewModel.NameProperty):
                CurrentNameInfo = message.NewValue;
                break;
            case nameof(FormUCViewModel.ClassProperty):
                CurrentClassInfo = message.NewValue;
                break;
            case nameof(FormUCViewModel.PhoneProperty):
                CurrentPhoneInfo = message.NewValue;
                break;
        }
    }
}

功能展示

传递变化的属性

输入框代码

属性变化,底下的TextBlock也会跟着变化

ObservableProperty可以添加可视化属性,让前端绑定

NotifyPropertyChangedRecipients可以通知订阅了的类,属性变化

public partial class FormUCViewModel:ObservableRecipient
{
    //现代化写法
    [ObservableProperty]
    [NotifyPropertyChangedRecipients]
    private string nameProperty;

    //现代化写法
    [ObservableProperty]
    [NotifyPropertyChangedRecipients]
    private string classProperty;

	//老式写法
    private string phoneProperty;

    public string PhoneProperty
    {
        get { return phoneProperty; }
        set {
            if (SetProperty(ref phoneProperty, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this, nameof(PhoneProperty), default, value));
            }
        }
    }


}

显示的TextBlock代码

属性变化接收到不同的message,可以用message.PropertyName来区分接收的属性

public partial class MainWindowViewModel:ObservableRecipient,IRecipient<PropertyChangedMessage<string>>
{
    [ObservableProperty]
    private string currentNameInfo;

    [ObservableProperty]
    private string currentClassInfo;

    [ObservableProperty]
    private string currentPhoneInfo;


    public MainWindowViewModel()
    {
        this.IsActive = true;
    }

    public void Receive(PropertyChangedMessage<string> message)
    {
        // 根据消息的属性名称更新相应的属性
        switch (message.PropertyName)
        {
            case nameof(FormUCViewModel.NameProperty):
                CurrentNameInfo = message.NewValue;
                break;
            case nameof(FormUCViewModel.ClassProperty):
                CurrentClassInfo = message.NewValue;
                break;
            case nameof(FormUCViewModel.PhoneProperty):
                CurrentPhoneInfo = message.NewValue;
                break;
        }
    }
}

image-20250509213207417

ToggleButton用NotifyPropertyChangedRecipients来通知订阅方属性变化了

[ObservableProperty]
[NotifyPropertyChangedRecipients]
private bool isAdd;

xaml

<ToggleButton IsChecked="{Binding IsAdd}"
              Grid.Row="1"
              Margin="5,8"
              HorizontalAlignment="Center"
              Style="{StaticResource ToggleButtonSwitch}"
              hc:VisualElement.HighlightBrush="{DynamicResource DangerBrush}" />

Receive接收到了数据要用(message.PropertyName来判断一下,以防接收到别的乱七八糟的数据(必须要弄,这个报错搞死我了

public partial class FormUCViewModel:ObservableRecipient,IRecipient<PropertyChangedMessage<bool>>
{

    public FormUCViewModel()
    {
        IsActive = true;
    }

    [ObservableProperty]
    private bool canAllow;

    public void Receive(PropertyChangedMessage<bool> message)
    {
        if (message.PropertyName == nameof(ListUCViewModel.IsAdd))
        {
            CanAllow = message.NewValue;
        }   

    }
   
}

xaml

<Button Grid.Row="3"
        Content="存入列表"
        Height="40"
        IsEnabled="{Binding CanAllow}"
        Command="{Binding AddButtonClickCommand}"
        Width="100" />

image-20250509154736779

传递普通的值

点击按钮,把信息传入listbox

表单代码

public partial class FormUCViewModel:ObservableRecipient
{
    [ObservableProperty]
    [NotifyPropertyChangedRecipients]
    private string nameProperty;



    [ObservableProperty]
    [NotifyPropertyChangedRecipients]
    private string classProperty;


    private string phoneProperty;

    public string PhoneProperty
    {
        get { return phoneProperty; }
        set {
            if (SetProperty(ref phoneProperty, value))
            {
                WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<string>(this, nameof(PhoneProperty), default, value));
            }
        }
    }

    [RelayCommand]
    void AddButtonClick()
    {
        Student student = new Student(NameProperty, ClassProperty, PhoneProperty);
        WeakReferenceMessenger.Default.Send(new ValueChangedMessage<Student>(student));
    }

}

列表代码

public class ListUCViewModel: ObservableRecipient,IRecipient<ValueChangedMessage<Student>>
{
    public ListUCViewModel()
    {
        lists.Add(new Student("张三", "三班", "123123123"));
        lists.Add(new Student("李四", "四班", "534343434"));
        lists.Add(new Student("王五", "六班", "876453534"));
        lists.Add(new Student("赵六", "二班", "123645634"));
        IsActive = true;
    }

    public ObservableCollection<Student> lists { get; set; } = new ObservableCollection<Student>();

    public void Receive(ValueChangedMessage<Student> message)
    {
        lists.Add(message.Value);
    }
}

依赖注入

安装包

Install-Package Microsoft.Extensions.Hosting
Install-Package Microsoft.Extensions.DependencyInjection

编写App.xaml.cs

public partial class App : Application
{
    public IHost _host;

    public App()
    {
        _host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddTransient<FormUCViewModel>();
                services.AddTransient<ListUCViewModel>();
                services.AddTransient<MainWindowViewModel>();
                services.AddTransient<ReciverUCViewModel>();
                services.AddTransient<SenderUCViewModel>();
                services.AddTransient<HelloServe>();
            })
            .Build();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var mainWindow = new MainWindow();
        var mainViewModel = _host.Services.GetRequiredService<MainWindowViewModel>();
        mainWindow.DataContext = mainViewModel;
        mainWindow.Show();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        base.OnExit(e);
        _host.Dispose();
    }
}

veiw界面更改数据上下文的引用方式

public partial class ListUC : UserControl
{
    public ListUC()
    {
        InitializeComponent();
        //this.DataContext=new ListUCViewModel();
        //修改为依赖注入的方式
        var app = Application.Current as App;
        if (app != null)
        {
            var viewModel = app._host.Services.GetRequiredService<ListUCViewModel>();
            this.DataContext = viewModel;
        }
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到