- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
是否有可能从我的 ViewModel 公开一个公共(public)事件,以便允许它绑定(bind)到我的 View 中的自定义 DependencyProperty?
我的应用程序是使用 .NET 4.5 框架用 C# 编写的。它具有 MVVM 架构,在 View 中没有代码隐藏和自定义 DependencyProperty 类,用于将 View 的 WPF 特定行为绑定(bind)到 ViewModel 公开的属性。
我希望 ViewModel 能够公开一组属性,这些属性表示 View 需要响应的事件。例如,当顶级 ViewModel 对象即将被处置时,我希望 WPF View 实现通过关闭相应的 Window 来响应。当配置过程显示对话窗口、用户输入并确认信息并且 ViewModel 已将其传递给模型并且不再需要时,可能会发生这种情况。
我知道有很多问题专门针对解决“ViewModel 的显示对话框”问题;这不是其中之一,我有解决方案。
我已经通读了 DependencyProperties 的 MSDN 文档,但找不到任何特定于绑定(bind)到事件属性的内容。
我想实现的是类似于下面的代码。此代码生成,但在显示 MainWindow 时导致典型的 System.Windows.Data Error: 40 : BindingExpression path error: 'RequestCloseEvent' property not found
错误。
我知道有很多问题与“请帮助我调试我的 System.Windows.Data 错误:40 问题”有关;这(可能)也不是其中之一。(但如果真的就是这样,我会很高兴。)
WindowBindableProperties.cs 中自定义 DependencyProperty 的来源:
using System;
using System.Threading;
using System.Windows;
namespace WpfEventBinding
{
public static class WindowBindableProperties
{
#region ViewModelTerminatingEventProperty
/// <summary>
/// Register the ViewModelTerminatingEvent custom DependencyProperty.
/// </summary>
private static DependencyProperty _viewModelTerminatingEventProperty =
DependencyProperty.RegisterAttached
(
"ViewModelTerminatingEvent",
typeof(ViewModelTerminatingEventHandler),
typeof(WindowBindableProperties),
new PropertyMetadata(null, ViewModelTerminatingEventPropertyChanged)
);
/// <summary>
/// Identifies the ViewModelTerminatingEvent dependency property.
/// </summary>
public static DependencyProperty ViewModelTerminatingEventProperty
{ get { return _viewModelTerminatingEventProperty; } }
/// <summary>
/// Gets the attached ViewModelTerminatingEvent dependecy property.
/// </summary>
/// <param name="dependencyObject">The window attached to the WindowViewModel.</param>
/// <returns>The ViewModelTerminatingEventHandler bound to this property</returns>
public static ViewModelTerminatingEventHandler GetViewModelTerminatingEvent
(DependencyObject dependencyObject)
{
return (dependencyObject.GetValue(ViewModelTerminatingEventProperty)
as ViewModelTerminatingEventHandler);
}
/// <summary>
/// Sets the ViewModelTerminatingEvent dependency property.
/// </summary>
public static void SetViewModelTerminatingEvent(
DependencyObject dependencyObject,
ViewModelTerminatingEventHandler value)
{
dependencyObject.SetValue(ViewModelTerminatingEventProperty, value);
}
/// <summary>
/// Gets the ViewModelTerminatingEvent dependency property.
/// </summary>
private static void ViewModelTerminatingEventPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
Window instance = d as Window;
if (null != instance)
{
if (null != e.OldValue)
{
throw new System.InvalidOperationException(
"ViewModelTerminatingEvent dependency property cannot be changed.");
}
if (null != e.NewValue)
{
// Attach the Window.Close() method to the ViewModel's event
var newEvent = (e.NewValue as ViewModelTerminatingEventHandler);
newEvent += new ViewModelTerminatingEventHandler(() => instance.Close());
}
}
}
#endregion
}
}
MainWindow.xaml 的来源:(此示例包含用于简化停止按钮实现的代码隐藏。)
<Window x:Class="WpfEventBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:WpfEventBinding"
v:WindowBindableProperties.ViewModelTerminatingEvent="{Binding Path=RequestCloseEvent}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="{Binding Path=CloseCommandName}" Click="StopButton_Click" ></Button>
</Grid>
</Window>
MainWindow.xaml.cs 的来源(代码隐藏):
using System.Windows;
namespace WpfEventBinding
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
MainWindowViewModel vm = (DataContext as MainWindowViewModel);
if (null != vm)
{
vm.Stop();
}
}
}
}
MainWindowViewModel.cs 的来源:
using System;
using System.ComponentModel;
namespace WpfEventBinding
{
public delegate void ViewModelTerminatingEventHandler();
class MainWindowViewModel
: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Raised by the ViewModel to indicate to the view that it is no longer required.
// Causes System.Windows.Data Error: 40 : BindingExpression path error. Is it
// Possible to bind to an 'event' property?
public event ViewModelTerminatingEventHandler RequestCloseEvent;
// This has to have the public 'get' to allow binding. Is there some way to
// do the same thing for the 'event'?
public String CloseCommandName { get; private set; }
public MainWindowViewModel()
{
CloseCommandName = "Close";
}
internal void Stop()
{
ViewModelTerminatingEventHandler RaiseRequestCloseEvent =
RequestCloseEvent;
if (null != RaiseRequestCloseEvent)
{
RaiseRequestCloseEvent();
}
}
internal void Start()
{
OnPropertyChanged("CloseCommandName");
OnPropertyChanged("ViewModelTerminatingEvent");
}
private void OnPropertyChanged(String propertyName)
{
PropertyChangedEventHandler RaisePropertyChangedEvent = PropertyChanged;
if (RaisePropertyChangedEvent != null)
{
var propertyChangedEventArgs = new PropertyChangedEventArgs(propertyName);
RaisePropertyChangedEvent(this, propertyChangedEventArgs);
}
}
}
}
App.xaml 的来源:
<Application x:Class="WpfEventBinding.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Application.Resources>
<!-- Nothing to see here. Move along... -->
</Application.Resources>
</Application>
App.xaml.cs 的来源
using System.Windows;
namespace WpfEventBinding
{
public partial class App : Application
{
public App()
{
Startup += new StartupEventHandler(App_Startup);
}
void App_Startup(object sender, StartupEventArgs e)
{
MainWindowViewModel vm = new MainWindowViewModel();
MainWindow window = new MainWindow();
// Make sure this is set before attempting binding!
window.DataContext = vm;
vm.Start();
window.Show();
}
}
}
似乎 public event ViewModelTerminatingEventHandler RequestCloseEvent;
语法不足以允许数据绑定(bind)发生。类似的问题是查看 public String CloseCommandName { get;私有(private)集;
被声明为 public String CloseCommandName;
而没有 { get;私有(private)集; }
。但是,没有 { get;私有(private)集; }
事件,它使用 {add{} remove{}}
语法(这也不能解决问题)。
我正在尝试的是否可行?如果可行,我错过了什么?
最佳答案
View closing 表示窗口关闭事件。所以你基本上想要对 View 中的事件使用react。我最近读了这个 arcticle , 有一个很好的图像
并且还提到了EventBehavior
的存在。
如果您不想隐藏任何代码,最好的办法是使用行为。行为是一个简单的附加属性,它可以执行操作,例如上升的应用程序范围的命令,然后 ViewModel
可以捕获这些操作而不会出现 MVVM
问题。
这是一个行为示例:
public static class FreezeBehavior
{
public static bool GetIsFrozen(DependencyObject obj)
{
return (bool)obj.GetValue(IsFrozenProperty);
}
public static void SetIsFrozen(DependencyObject obj, bool value)
{
obj.SetValue(IsFrozenProperty, value);
}
public static readonly DependencyProperty IsFrozenProperty =
DependencyProperty.RegisterAttached("IsFrozen", typeof(bool), typeof(FreezeBehavior), new PropertyMetadata(OnIsFrozenChanged));
private static void OnIsFrozenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
var freezable = d as Freezable;
if (freezable != null && freezable.CanFreeze)
freezable.Freeze();
}
}
}
是这样使用的
<DropShadowEffect ShadowDepth="2" local:FreezeBehavior.IsFrozen="True"/>
它可以附加到任何 freezable 上以卡住它。在您的情况下,您想订阅事件并调用命令或设置属性,或任何通知 ViewModel
的内容。
关于c# - 公开 ViewModel 事件以绑定(bind)到自定义 DependencyProperty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24936700/
例如 Form1 frm1 = new Form1(); TextBox tb = new TextBox(); frm1.Controls.Add(tb); 现在我不能说 f
我有一个日期过滤器,我已经在我的 View 中公开了它。我想让界面更加用户友好并加强它的外观。我不想选择日期,而是从以下选项中进行选择。 最后一天 上周 去年 全部 然后,这将过滤日期字段。这可能吗?
如何向用户公开我的用户控件组件之一的 ActualWidth 属性? 我找到了很多关于如何通过创建新的依赖属性和绑定(bind)来公开普通属性的示例,但没有关于如何公开像 ActualWidth 这样
Github 最近推出了项目功能。 当项目处于 repo 级别时,如果 repo 本身是公开的,那么任何人都可以访问这些项目。 但是,组织级别的项目仅对组织成员可见。 例如,https://githu
我想要从我的网络服务器访问 JavaScript 文件。 以便任何人都可以在其网站中访问和引用它。 e-g 假设 abcxyzserver.com 是我的网络服务器。 www.abcxyzserv
尝试使用curl命令上传到blob存储 curl --upload-file --url "https://.blob.core.windows.net//" 但不断收到“HTTP/1.1 404
我正在尝试获取 Canvas 的上下文,显然我收到错误Uncaught TypeError: Cannot call method 'getContext' of null 显然我在它初始化之前就得到
我正在对设置 HA 集群的解决方案进行故障排除。虽然我知道应用程序执行故障转移和故障回复所需的端口,但不知何故 dockerized 解决方案不起作用。我怀疑有一些我还不知道的端口。 目前,我的 EX
我试图在能够使用 Helm 运行的k8集群中设置Prometheus。当我使用外部IP将Prometheus-Server作为LoadBalancer服务公开时,访问仪表板。 当我尝试将此服务配置为C
我知道关于这个主题也有类似的问题,但我不完全确定他们正在解决同样的问题。所以要明确的是... 我有一个现有的类库,其中包含用于类型、业务逻辑和数据访问的命名空间。逻辑和数据访问命名空间中的类是静态的,
尝试使用curl命令上传到blob存储 curl --upload-file --url "https://.blob.core.windows.net//" 但不断收到“HTTP/1.1 404
1.)执行以下命令生成一个随机数,用于后面的步骤 NUMBER=$[ ( $RANDOM % 1000 ) + 1 ] echo $NUMBER 注意:将句子 your random number 替
类似这样的问题有很多,但仍然无法得到我真正想要的,而且它们都有一些与我不同的地方,那就是:我有一个 UserControl: 在名为UCProject 的类库项目中单独构建; UCProject 项目
我有一个这样的基类: public class BaseModalCommand { protected object m_commandArgument; protected i
给定以下 JQuery 插件。是否可以将变量“元素”公开给插件外部的 javascript?如果是这样,这是怎么做到的?对于此插件外部的 javascript,访问“元素”的语法是什么? (funct
我有两个使用 jhipster 创建的微服务。 (ms1 和 ms2) 我使用 AuthorizedFeignClient 在两个微服务之间进行通信。 ms1 有一些 DTO 类,用作 REST AP
我正在使用错误跟踪软件来报告网络浏览器中发生的任何错误,但我的生产站点上的代码已缩小。因此,调试几乎是不可能的(变量名被更改等)。 我想将完整的源映射文件投入生产,以便我可以调试这些错误,但在这样做时
我在 Kotlin 公开库中可以找到的所有 Material 都假定该表具有一个主标识列,因此在大多数示例中显示的实体继承了 IntEntity 抽象类。例如: class UserLocation(
我有一个类 (Capsule),它有很多 protected 方法 (30+)。这个想法是允许开发人员扩展此类并在类 (ImADev) 中使用 protected 方法,但将其留给开发人员将它们公开为
Tomcat 日志位置是: /apache/apache-tomcat-8.0.15/logs 允许通过浏览器访问这些日志的标准方法是什么? 为此启用 Tomcat 目录列表标准吗? 最佳答案 我曾在
我是一名优秀的程序员,十分优秀!