gpt4 book ai didi

c# - 在 WPF 中轻松地将通知传播到 UI

转载 作者:太空宇宙 更新时间:2023-11-03 12:43:34 25 4
gpt4 key购买 nike

所以我看到了一些对与此类似问题的回答,但我想知道我正在考虑的某种范例在 C# 中是否可行。首先,我将列出问题:

我有一个用 C# 开发的 MVVM 应用程序。模型的属性会发生变化,当模型中的单个属性发生变化时,它通常会影响 View 模型中的多个属性。所以 View 模型监听模型的变化。 View 会监听 View 模型的变化。

在我的 View 模型中,我最终得到一些如下所示的代码:

private void OnModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
string prop_name = e.PropertyName;
if (prop_name.Equals("some_property_on_the_model"))
{
NotifyPropertyChanged("some_property_on_the_view_model");
NotifyPropertyChanged("some_property_on_the_view_model");
NotifyPropertyChanged("some_property_on_the_view_model");
NotifyPropertyChanged("some_property_on_the_view_model");
NotifyPropertyChanged("some_property_on_the_view_model");
}
else if (...)
{
... etc ...
}
}

这很烦人,因为它看起来很乱。如果我在向 View 模型添加新属性后忘记编辑此函数,则很容易导致错误。

所以这是我希望做的,但我不知道这是否可能。所以我希望你们中的一位能帮助我了解这是否可能。

如果我可以使用 C# 的“属性”功能来处理属性更改传播,那就太棒了。

所以也许是这样的:

[ListenToModelProperty("some_property_on_the_model")]
[OnPropertyChanged("MyButtonVisibility")]
public Visibility MyButtonVisibility
{
get
{
if (model.some_property_on_the_model == true)
{
return Visibility.Visible;
}
else
{
return Visibility.Hidden;
}
}
}

private void OnModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
prop_name = e.PropertyName;

foreach (var property in view_model)
{
var attributes = property.GetCustomAttributes(typeof(ListenToModelPropertyAttribute));
var descriptions = attributes.Select(x => x.Description);
if (descriptions.Contains(prop_name))
{
notification_to_make = property.GetCustomAttributes(typeof(OnPropertyChangedAttribute));
string notification_string = notification_to_make[0].Description;
NotifyPropertyChanged(notification_string);
}
}
}

请注意,上面的代码并不是真正的代码。它肯定不会编译,也不会工作。但我想看看在 C# 中是否可以实现类似上面的内容。是否可以使用属性来做这样的事情?或者是否有一个图书馆可以让这样的事情成为可能?

最佳答案

我已经知道怎么做了!这很简单。我会在这里贴出相关代码,有兴趣的可以在我刚刚制作的这个github仓库中找到所有代码:https://github.com/davepruitt/model-subscribe

首先,我创建了一个自定义属性类。这是一个简单的类,它将字符串数组作为其构造函数的参数。这允许您监听模型上的多个属性以进行更改。它看起来像这样:

using System;
using System.Collections.Generic;

namespace TestPropagationOfPropertyChanges
{
[AttributeUsage(AttributeTargets.All)]
public class ListenForModelPropertyChangedAttribute : System.Attribute
{
public List<string> ModelPropertyNames = new List<string>();

public ListenForModelPropertyChangedAttribute (string [] propertyNames)
{
ModelPropertyNames.AddRange (propertyNames);
}
}
}

然后我创建了我的模型。为了简单起见,它只包含两个属性。它们是存储“名字”和“姓氏”的字符串:

using System;
using System.ComponentModel;

namespace TestPropagationOfPropertyChanges
{
public class Model : NotifyPropertyChangedObject
{
#region Constructors

public Model ()
{
}

#endregion

#region Private data members

private string _first = string.Empty;
private string _last = string.Empty;

#endregion

#region Public properties

public string FirstName
{
get
{
return _first;
}
set
{
_first = value;
NotifyPropertyChanged ("FirstName");
}
}

public string LastName
{
get
{
return _last;
}
set
{
_last = value;
NotifyPropertyChanged ("LastName");
}
}

#endregion
}
}

在这种情况下, View 模型具有“全名”属性。所以它想要监听模型中名字或姓氏发生的任何变化,然后对其中任何一个的变化使用react。我意识到这不是使用这种系统的最佳“真实世界”场景,但它确实有助于说明这个概念。我的 View 模型的第一部分如下:

using System;

namespace TestPropagationOfPropertyChanges
{
public class ViewModel : NotifyPropertyChangedObject
{
#region Private data members

//This is public for testing purposes
public Model _model = new Model();

#endregion

#region Constructors

public ViewModel ()
{
_model.PropertyChanged += ReactToModelPropertyChanged;
}

#endregion

#region Properties

[ListenForModelPropertyChangedAttribute(new string [] {"FirstName", "LastName"})]
public string FullName
{
get
{
return _model.FirstName + _model.LastName;
}
}

最后, View 模型以响应模型变化的方法结束。通常,在大型复杂的应用程序中,此方法可能包含一个大型 if-else 语句,其中包含对 NotifyPropertyChanged 的​​大量调用。相反,我们现在只是遍历 View 模型的属性并查看哪些订阅了已更改的模型属性。见下文:

void ReactToModelPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//Get the name of the property that was changed on the model
string model_property_changed = e.PropertyName;

//Get a System.Type object representing the current view-model object
System.Type t = typeof(ViewModel);

//Retrieve all property info for the view-model
var property_info = t.GetProperties();

//Iterate through each property
foreach (var property in property_info)
{
//Get the custom attributes defined for this property
var attributes = property.GetCustomAttributes (false);
foreach (var attribute in attributes)
{
//If the property is listening for changes on the model
var a = attribute as ListenForModelPropertyChangedAttribute;
if (a != null)
{
//If the property that was changed on the model matches the name
//that this view-model property is listening for...
if (a.ModelPropertyNames.Contains(model_property_changed))
{
//Notify the UI that the view-model property has been changed
NotifyPropertyChanged (property.Name);
}
}
}
}
}

总的来说,它运行良好,正是我所需要的。此代码可以很容易地扩展,以便为那些感兴趣的人提供更多功能。

关于c# - 在 WPF 中轻松地将通知传播到 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38112175/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com