gpt4 book ai didi

c# - WPF应用程序-调用事件操作时不会触发监听方法

转载 作者:行者123 更新时间:2023-12-03 10:44:19 25 4
gpt4 key购买 nike

我有一个WPF MVVM应用程序。我有一个名为MainWindowViewModel的类和一个名为TileMenuViewModel的类,这两个类都是从BaseViewModel派生的。基本要做的就是实现INotifyPropertyChangedINotifyDataErrorInfo,同时保留错误的Dictionary<string, List<string>>进行验证。

在我的MainWindowViewModel中,我实例化了
private TileMenuViewModel _tileMenuViewModel = new TileMenuViewModel();
在我的TileMenuViewModel中,我有一个public event Action NavToCampaings = new delegate {};
现在在MainWindowViewModel构造函数中,我订阅此事件:
_tileMenuViewModel.NavToCampaings += OnNavToCampaigns;
但是,当我在某个时候从TileMenuViewModel调用事件时,例如NavToCampaigns();,我的已订阅事件(OnNavToCampaignsMainWindowViewModel)不会被调用。当我使用断点进行调试时,可以看到NavToCampaigns();事件Action被调用,但其值为null。当我通过实例化TileMenuViewModel的MainWindowViewModel构造时,调试器也不会输入TileMenuViewModel。但是,我的程序的其余部分都按预期工作,并且看到“平铺菜单”正在工作。

对于我的一生,我无法弄清楚自己在做什么错。有任何想法吗?为简便起见,这是我的三个类(class):

MainWindowViewModel.cs

namespace MyApp.Main
{
public class MainWindowViewModel : BaseViewModel
{
private string _windowsUser = WindowsIdentity.GetCurrent().Name;
private TileMenuViewModel _tileMenuViewModel = new TileMenuViewModel();
private CmpCampaignListViewModel _cmpCampaignListViewModel = new CmpCampaignListViewModel();
private NapTransferCampaignListViewModel _ntCampaignListViewModel = new NapTransferCampaignListViewModel();

public string WindowsUser { get { return _windowsUser; } }
public string WindowTitle { get; set; }

private BaseViewModel _currentViewModel;

public BaseViewModel CurrentViewModel
{
get { return _currentViewModel; }
set { SetProperty(ref _currentViewModel, value); }
}

public MainWindowViewModel()
{
WindowTitle = String.Format("MyApp - {0}", WindowsUser);
NavCommand = new RelayCommand<string>(OnNav);
AddNewCmpCampaignCommand = new RelayCommand(OnAddNewCmpCampaign);
CurrentViewModel = _tileMenuViewModel;
_tileMenuViewModel.NavToCampaings += OnNavToCampaigns;

}

public RelayCommand<string> NavCommand { get; private set; }
public RelayCommand AddNewCmpCampaignCommand { get; private set; }

public void OnNav(string destination)
{
switch (destination)
{
case "CmpCampaignList":
CurrentViewModel = _cmpCampaignListViewModel;
break;
case "NtCampaignList":
CurrentViewModel = _ntCampaignListViewModel;
break;
case "TileMenu":
CurrentViewModel = _tileMenuViewModel;
break;
default:
CurrentViewModel = _tileMenuViewModel;
break;
}
}

public void OnAddNewCmpCampaign()
{
var editCampaignWindow = new AddEditCmpCampaignWindow();
editCampaignWindow.Show();
}

private void OnNavToCampaigns()
{
CurrentViewModel = _cmpCampaignListViewModel;
//OnNav("CmpCampaignList");
}
}
}

TileMenuViewModel.cs
namespace MyApp.Main
{
public class TileMenuViewModel : BaseViewModel
{
public TileMenuViewModel()
{
NavToCampaignsCommand = new RelayCommand(OnNavToCampaigns);
}

public RelayCommand NavToCampaignsCommand { get; private set; }
public event Action NavToCampaings = delegate { };

private void OnNavToCampaigns()
{
NavToCampaings();
}
}
}

BaseViewModel.cs
namespace MyApp.Infrastructure
{
public class BaseViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
{
private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>(
);

public event PropertyChangedEventHandler PropertyChanged = delegate { };
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };

public bool HasErrors
{
get { return _errors.Count > 0; }
}

public IEnumerable GetErrors(string propertyName)
{
return _errors.ContainsKey(propertyName) ? _errors[propertyName] : null;
}

protected virtual void SetProperty<T>(ref T member, T val,
[CallerMemberName] string propertyName = null)
{
if (!object.Equals(member, val))
{
member = val;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
ValidateProperty(propertyName, val);
}

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

private void ValidateProperty<T>(string propertyName, T value)
{
var results = new List<ValidationResult>();
ValidationContext context = new ValidationContext(this);
context.MemberName = propertyName;
Validator.TryValidateProperty(value, context, results);

if (results.Any())
{
_errors[propertyName] = results.Select(c => c.ErrorMessage).ToList();
}
else
{
_errors.Remove(propertyName);
}

ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}

}
}

最佳答案

编辑:
我解决了为什么它不起作用的问题:在用于它的 View 中,我有一个TileMenuViewModel的新实例;我在使用viewmodel进行测试后忘记了它。它将DataContext设置为触发事件的新实例,并且MainWindowViewModel正在监听其自己的TileMenuViewModel实例的事件。所以我简单地删除了这一行:

DataContext = new TileMenuViewModel();

从我的 TileMenuView中获取并整理了我的 Activity 。我会将线程留在这里,以供任何可能觉得有用的人使用。

我仍然想知道将事件作为静态使用是一个好还是坏的主意?

原答案:

我最终通过将事件标记为静态解决了这一问题。 IE:
public static event Action NavToCampaings = delegate { };
当然,我不使用类实例来订阅事件:
TileMenuViewModel.NavToCampaings += OnNavToCampaigns;
但是,我仍然想知道为什么我不能让该事件系统作为实例成员与事件一起工作。并且如果使用事件static会带来任何问题(或者如果这只是一种不好的做法?)

任何解释都会被贬低。

关于c# - WPF应用程序-调用事件操作时不会触发监听方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34412181/

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