编辑:我已经重新设计了我的问题,因为我似乎有点懒惰。
Edit2:更新了代码,忘记了一件事,并在ViewUcBase.UserInputErrorHandler上编写了EventArg而不是UserInputEventArgs
Edit3:改变了VMBase,仍然没有努力。
所以我有这个(部分)当前设置:https://www.dropbox.com/s/8ibsbwv2faigxal/MVVM%20Messaging.png?dl=0
现在我想做以下事情:
考虑:
无效的代码。我知道我错过了什么,但似乎无法找到什么。 (最后的错误)
public interface IViewModelComponent
{
event EventHandler UserInputError;
//just to show I want multiple events.
event EventHandler SomeOtherEvent;
}
public class VMBase: IViewModelComponent
{
public event EventHandler<UserInputEventArgs> UserInputError;
protected virtual void OnUserInputError(UserInputEventArgs e)
{
EventHandler<UserInputEventArgs> handler = UserInputError;
if (handler != null)
{
handler(this, e);
}
}
//just to show I want multiple events.
public event EventHandler SomeOtherEvent;
...
}
public class UserInputEventArgs: EventArgs
{
public string ErrorMessage { get; set; }
}
public class AssetForm : VMBase
{
private void SomethingBadHappened()
{
UserInputEventArgs args = new UserInputEventArgs;
args.ErrorMessage = "This bad thing hapened";
OnUserInputError(args);
}
}
public class ViewUcBase : UserControl, IViewComponent
{
//EDIT: Forgot the next line
public IViewModelComponent VM { get; set; }
//Default implementation of what should be done with the event.
public virtual void UserInputErrorHandler(object sender, UserInputEventArgs e)
{
string header = string.Format("{0} - InputError",DisplayName);
MessageBox.Show(e.ErrorMessage,header,MessageBoxButton.OK,MessageBoxImage.Exclamation);
}
//Subscribing to the event in the base class so it always gets handled.
public ViewUcBase()
{
VM.UserInputError += UserInputErrorHandler; //No overload for 'UserInputErrorHandler' matches delegate 'System.EventHandler'
}
}
}
我希望此更新可以更好地解释事情,并且我没有错过任何内容。
答案 0 :(得分:0)
我使用 发布订阅模式 来处理复杂的类依赖项:
<强>视图模型:强>
public class ViewModel : ViewModelBase
{
public ViewModel()
{
CloseComand = new DelegateCommand((obj) =>
{
MessageBus.Instance.Publish(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, null);
});
}
}
<强>窗口:强>
public partial class SomeWindow : Window
{
Subscription _subscription = new Subscription();
public SomeWindow()
{
InitializeComponent();
_subscription.Subscribe(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, obj =>
{
this.Close();
});
}
}
您可以利用Bizmonger.Patterns获取MessageBus。
<强> MessageBus 强>
public class MessageBus
{
#region Singleton
static MessageBus _messageBus = null;
private MessageBus() { }
public static MessageBus Instance
{
get
{
if (_messageBus == null)
{
_messageBus = new MessageBus();
}
return _messageBus;
}
}
#endregion
#region Members
List<Observer> _observers = new List<Observer>();
List<Observer> _oneTimeObservers = new List<Observer>();
List<Observer> _waitingSubscribers = new List<Observer>();
List<Observer> _waitingUnsubscribers = new List<Observer>();
int _publishingCount = 0;
#endregion
public void Subscribe(string message, Action<object> response)
{
Subscribe(message, response, _observers);
}
public void SubscribeFirstPublication(string message, Action<object> response)
{
Subscribe(message, response, _oneTimeObservers);
}
public int Unsubscribe(string message, Action<object> response)
{
var observers = new List<Observer>(_observers.Where(o => o.Respond == response).ToList());
observers.AddRange(_waitingSubscribers.Where(o => o.Respond == response));
observers.AddRange(_oneTimeObservers.Where(o => o.Respond == response));
if (_publishingCount == 0)
{
observers.ForEach(o => _observers.Remove(o));
}
else
{
_waitingUnsubscribers.AddRange(observers);
}
return observers.Count;
}
public int Unsubscribe(string subscription)
{
var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription).ToList());
observers.AddRange(_waitingSubscribers.Where(o => o.Subscription == subscription));
observers.AddRange(_oneTimeObservers.Where(o => o.Subscription == subscription));
if (_publishingCount == 0)
{
observers.ForEach(o => _observers.Remove(o));
}
else
{
_waitingUnsubscribers.AddRange(observers);
}
return observers.Count;
}
public void Publish(string message, object payload)
{
_publishingCount++;
Publish(_observers, message, payload);
Publish(_oneTimeObservers, message, payload);
Publish(_waitingSubscribers, message, payload);
_oneTimeObservers.RemoveAll(o => o.Subscription == message);
_waitingUnsubscribers.Clear();
_publishingCount--;
}
private void Publish(List<Observer> observers, string message, object payload)
{
Debug.Assert(_publishingCount >= 0);
var subscribers = observers.Where(o => o.Subscription.ToLower() == message.ToLower());
foreach (var subscriber in subscribers)
{
subscriber.Respond(payload);
}
}
public IEnumerable<Observer> GetObservers(string subscription)
{
var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription));
return observers;
}
public void Clear()
{
_observers.Clear();
_oneTimeObservers.Clear();
}
#region Helpers
private void Subscribe(string message, Action<object> response, List<Observer> observers)
{
Debug.Assert(_publishingCount >= 0);
var observer = new Observer() { Subscription = message, Respond = response };
if (_publishingCount == 0)
{
observers.Add(observer);
}
else
{
_waitingSubscribers.Add(observer);
}
}
#endregion
}
}
<强>订阅强>
public class Subscription
{
#region Members
List<Observer> _observerList = new List<Observer>();
#endregion
public void Unsubscribe(string subscription)
{
var observers = _observerList.Where(o => o.Subscription == subscription);
foreach (var observer in observers)
{
MessageBus.Instance.Unsubscribe(observer.Subscription, observer.Respond);
}
_observerList.Where(o => o.Subscription == subscription).ToList().ForEach(o => _observerList.Remove(o));
}
public void Subscribe(string subscription, Action<object> response)
{
MessageBus.Instance.Subscribe(subscription, response);
_observerList.Add(new Observer() { Subscription = subscription, Respond = response });
}
public void SubscribeFirstPublication(string subscription, Action<object> response)
{
MessageBus.Instance.SubscribeFirstPublication(subscription, response);
}
}
答案 1 :(得分:0)
我知道这是愚蠢的事情,而且确实如此。
我正在混合来自https://msdn.microsoft.com/en-us/library/9aackb16%28v=vs.110%29.aspx的两个例子。所以我更新了所有
"Eventhandler" to "EventHandler<UserInputEventArgs>"
现在正在运作。
抱歉浪费你的时间。
完整的工作代码:
public interface IViewModelComponent
{
event EventHandler<UserInputEventArgs> UserInputError;
}
public class VMBase: IViewModelComponent
{
public event EventHandler<UserInputEventArgs> UserInputError;
protected virtual void OnUserInputError(UserInputEventArgs e)
{
EventHandler<UserInputEventArgs> handler = UserInputError;
if (handler != null)
{
handler(this, e);
}
}
}
public class UserInputEventArgs: EventArgs
{
public string ErrorMessage { get; set; }
}
public class AssetForm : VMBase
{
private void SomethingBadHappened()
{
UserInputEventArgs args = new UserInputEventArgs;
args.ErrorMessage = "This bad thing hapened";
OnUserInputError(args);
}
}
public class ViewUcBase : UserControl, IViewComponent
{
//EDIT: Forgot the next line
public IViewModelComponent VM { get; set; }
//Default implementation of what should be done with the event.
public virtual void UserInputErrorHandler(object sender, UserInputEventArgs e)
{
string header = string.Format("{0} - InputError",DisplayName);
MessageBox.Show(e.ErrorMessage,header,MessageBoxButton.OK,MessageBoxImage.Exclamation);
}
//Subscribing to the event in the base class so it always gets handled.
public ViewUcBase()
{
VM.UserInputError += UserInputErrorHandler; //No overload for 'UserInputErrorHandler' matches delegate 'System.EventHandler'
}
}
}