我正在开发符合MVVM模式的cardgame。我的模型包含玩家,手和牌以及游戏及其规则。 这里有2个课程不好看:" card"有#"已提交"事件:当玩家点击卡片的图像时,提交的事件会触发。这会触发UI将卡从手移动到窗口的中心。 接下来我有一个"技巧",所有玩家都添加一张卡片。当技巧已满时,它会触发TrickFull事件:这会触发UI以显示技巧中的牌,然后清除表格。
在游戏过程中,TrickFull事件在最后一张卡提交后会触发纳秒。这意味着在显示第4张卡之前清除该表。我希望能够强制UI在Trickfull事件之前处理cardsubmitted事件。 我试图通过Thread.Sleep(这不起作用)来实现这一点,我也尝试将TrickFull事件移动到游戏类(意味着它会在稍后被触发)。这有效,但看起来确实不合适。我已经研究了锁定事件(但这似乎没有办法),直接控制Dispatcher,更改优先级,或者可能异步调用事件并在EndInvoke中以某种方式阻塞这些事件。 我想知道最好的解决办法是什么。我的研究表明,事件可能不是这种行为的最佳模式,但我很难过。请问有光明的人请告诉我如何解决这个(可能是建筑性的)缺陷?
下面的代码,要注意:荷兰的类名和内容
卡(= Kaart)
public class Kaart : IComparable<Kaart>
{
public readonly Kleur Kleur;
public readonly Waarde Waarde;
public Kaart(Kleur kleur, Waarde waarde)
{
Kleur = kleur;
Waarde = waarde;
}
public event KaartGespeeld Opgegooid;
public delegate void KaartGespeeld(Kaart kaart);
public void Opgooien()
{
Opgegooid?.Invoke(this);
}
public int CompareTo(Kaart other)
{
var comparer = new KlaverjasComparer(null, null);
return comparer.Compare(this, other);
}
public Speler Speler { get; set; }
}
Trick(= Slag)
public class Slag
{
private readonly List<Kaart> _kaarten;
[Browsable(false)]
public IReadOnlyList<Kaart> Kaarten => _kaarten;
public Slag(Kleur troef)
{
_kaarten = new List<Kaart>(4);
Troef = troef;
}
public Speler Winnaar { get; private set; }
public int Punten => PuntenTeller.Punten(this);
public int Roem => PuntenTeller.Roem(this);
[Browsable(false)]
public Kleur Troef { get; }
public Kleur GevraagdeKleur { get; set; }
[Browsable(false)]
public bool Vol =>_kaarten.Count == 4;
public void Add(Kaart kaart)
{
if (!Vol)
{
if (_kaarten.Count == 0)
{
GevraagdeKleur = kaart.Kleur;
}
_kaarten.Add(kaart);
}
else
{
throw new Exception("Te veel kaarten in een slag");
}
if (!Vol) return;
Winnaar = bepaalHoogsteKaart(this).Speler;
VolleSlag?.Invoke(this);
}
public event SlagIsVol VolleSlag;
public delegate void SlagIsVol(Slag slag);
}
视图模型:
public TafelViewModel(Boompje boompje)
{
Speler1 = boompje.Deelnemers[0];
Speler2 = boompje.Deelnemers[1];
Speler3 = boompje.Deelnemers[2];
Speler4 = boompje.Deelnemers[3];
Troef = boompje.Potje.Troef;
//boompje.SlagIsVol += Boompje_SlagIsVol;
// ToDo: als ik naar dit event kijk gaat het mis
boompje.Potje.Slag.VolleSlag += Boompje_SlagIsVol;
boompje.Potje.TroefGedraaid += delegate { Troef = boompje.Potje.Troef; };
foreach (Speler _deelnemer in boompje.Deelnemers)
{
foreach (Kaart _kaart in _deelnemer.Hand)
{
_kaart.Opgegooid += moveKaart;
}
_deelnemer.DoeIkHet += DeelnemerOnDoeIkHet;
}
_spelerKaart = new Dictionary<Speler, string>
{
{Speler1, "Kaart1"},
{Speler2, "Kaart2"},
{Speler3, "Kaart3"},
{Speler4, "Kaart4"}
};
_spelerRichting = Dictionary.SpelersRichting(boompje.Deelnemers);
WinnaarVisible = Visibility.Hidden;
}
private void Boompje_SlagIsVol(Slag slag)
{
WinnaarVisible = Visibility.Visible;
Richting = _spelerRichting[slag.Winnaar];
Application.DoEvents();
Thread.Sleep(2000);
Kaart1 = null;
Kaart2 = null;
Kaart3 = null;
Kaart4 = null;
WinnaarVisible = Visibility.Hidden;
}
private void moveKaart(Kaart kaart)
{
PropertyInfo prop = GetType().GetProperty(_spelerKaart[kaart.Speler]);
prop?.SetValue(this, kaart);
}
public void OpKaartGeklikt(Kaart kaart)
{
if (kaart.Speler != Speler3)
{
return;
}
Speler3.SpeelKaart(kaart);
}
}
}
答案 0 :(得分:0)
在ViewModel中设置ManualResetEvent
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
将此对象传递给您的Kaart
ManualResetEvent _manualResetEvent;
public Kaart(Kleur kleur, Waarde waarde, ManualResetEvent manualResetEvent)
{
Kleur = kleur;
Waarde = waarde;
_manualResetEvent = manualResetEvent;
}
这是在添加卡时调用的方法我假设
public void Opgooien()
{
Opgegooid?.Invoke(this);
_manualResetEvent.Set();
}
主要部分(您还需要将ManualResetEvent
传递给Slag
对象。
public void Add(Kaart kaart)
{
if (!Vol)
{
if (_kaarten.Count == 0)
{
GevraagdeKleur = kaart.Kleur;
}
_kaarten.Add(kaart);
}
else
{
throw new Exception("Te veel kaarten in een slag");
}
if (!Vol) return;
Winnaar = bepaalHoogsteKaart(this).Speler;
var result = _manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
if(!result)
{
/* Did not receive signal in 5 seconds */
}
VolleSlag?.Invoke(this);
_manualResetEvent.Reset();
}
只是基本概念,由于您的代码语言并且在示例中缺少某些部分,它可能无法正常工作,但您应该抓住这个想法