gpt4 book ai didi

c# - 当绑定(bind)属性的值未更改时,是否可以说服 PropertyChangedCallback 运行?

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

我的应用程序使用 MVVM 架构,ViewModel 不了解 View。当 ViewModel 对象需要显示新 View 时,它会公开一个公共(public) ShowNewView 属性,该属性是一个类基于我的 ViewModel 基类的对象。 WPF View 将自定义 DependencyProperty 绑定(bind)到此,并使用 PropertyChangedCallback 构造和显示适当的窗口。

这在第一次设置 ShowNewView 属性时一切正常。但是,如果用户关闭窗口然后尝试重新打开它,则在引发 PropertyChanged 事件并且未调用 PropertyChangedCallback 时,ShowNewView 属性的值没有更改。

为了“欺骗”DependencyProperty 检测值已更改(即使存储在 ViewModel 的属性中的值可能实际上没有更改),我使用了 SetCurrentValue 公开的方法Window 类强制 DependencyProperty 的值为 null

#region ShowNewViewProperty

private static readonly DependencyProperty _ShowNewViewProperty =
DependencyProperty.RegisterAttached
(
"ShowNewView",
typeof(IRootViewModel),
typeof(WpfViewWindow),
new PropertyMetadata(ShowNewViewPropertyChanged)
);

public static DependencyProperty ShowNewViewProperty { get { return _ShowNewViewProperty; } }

public static IRootViewModel GetShowNewView(Window source)
{
return (IRootViewModel)source.GetValue(ShowNewViewProperty);
}

public static void SetShowNewView(Window target, IRootViewModel value)
{
target.SetValue(ShowNewViewProperty, value);
}

private static void ShowNewViewPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WpfViewWindow window = d as WpfViewWindow;
IRootViewModel newValue = e.NewValue as IRootViewModel;
if ((null != window) && (null != newValue))
{
// Create a child WpfViewWindow. This method is part of my
// framework that uses ResourceDictionary entries, imported by MEF
// to locate the View class corresponding to the ViewModel parameter's
// class.
WpfViewWindow modelessWindow = window.CreateWpfViewWindow(newValue);
if (null != modelessWindow)
{
// Show the new WpfViewWindow.
modelessWindow.Show();
}

// Clear the current value so that the next PropertyChanged event
// is processed even if the underlying value has not actually changed.
window.SetCurrentValue(ShowNewViewProperty, null);
}
}

#endregion

从技术上讲,这是可行的,因为它会导致在 PropertyChanged 事件触发时运行回调,而不管值是否实际更改。但是,每次更新 ViewModel 的属性时都会(递归地)调用两次回调:一次响应 ViewModel 的事件,一次响应调用的 SetCurrentValue 方法。

这里有许多问题与 PropertyChangedCallback 在其他情况下未被调用或未被多次调用有关。

是否有更优雅的方法来实现此目的,不会导致回调针对来自 ViewModel 的每个 PropertyChanged 事件运行两次? IE。有什么方法可以绕过框架检查以验证旧值和新值是否不同?

澄清

正在创建的 View 不一定总是 WPF 窗口,例如,在我的单元测试中它是一个模拟,而在项目的后期它可能是一个单独的日志程序集。也不是所有的 ViewModel 对象都来自同一个程序集,众所周知,将来需要额外的功能,但具体细节目前尚未定义。该应用程序允许用户通过简单的网络连接设备。最初网络是 RS-485 上的 ModbusRTU,但是,最终客户可能希望使用 CANOpen 或 Profinet 或其他一些传输层,我必须提供一种插件机制,允许在不更改现有功能的情况下添加新功能代码。

公平地说,我可以使用几种替代机制来实现相同的结果(即让 ViewModel 请求创建一个新 View ),但我想知道是否有办法制作 DependencyPropety “忘记”它之前的值是什么。

最佳答案

此类问题的通常解决方案是从 ShowNewViewPropertyChanged 方法中提取代码并将其放入不同的方法中:

private void SomeNewMethod(IRootViewModel newValue)
{
// Create a child WpfViewWindow. This method is part of my
// framework that uses ResourceDictionary entries, imported by MEF
// to locate the View class corresponding to the ViewModel parameter's
// class.
WpfViewWindow modelessWindow = CreateWpfViewWindow(newValue);
if (null != modelessWindow)
{
// Show the new WpfViewWindow.
modelessWindow.Show();
}

// Clear the current value so that the next PropertyChanged event
// is processed even if the underlying value has not actually changed.
SetCurrentValue(ShowNewViewProperty, null);
}

现在您可以简单地从 ShowNewViewPropertyChanged 处理程序和您想要的任何其他地方调用该方法:

private static void ShowNewViewPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WpfViewWindow window = d as WpfViewWindow;
IRootViewModel newValue = e.NewValue as IRootViewModel;
if ((null != window) && (null != newValue))
{
window.SomeNewMethod(newValue);
}
}

关于c# - 当绑定(bind)属性的值未更改时,是否可以说服 PropertyChangedCallback 运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25602238/

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