private ViewBuilder AddTssClientRun(Expression <Func <ITsString> > fetchString, Func <ITsString> fetcher, TssClientRun run) { ParaBox para = InsertParaOrRun(run); // Try to hook an event for notification of changes to the property. var mexp = (fetchString.Body as MemberExpression); var argExp = Expression.Lambda <Func <object> >(mexp.Expression); Type type = mexp.Member.DeclaringType; string name = mexp.Member.Name; EventInfo einfo = type.GetEvent(name + "Changed"); var target = argExp.Compile().Invoke(); if (einfo == null) { MakeHookupForString(fetcher, run, name, target, para); } else { var stringHookup = new TssHookup(target, fetcher, hookup => einfo.AddEventHandler(target, new EventHandler <EventArgs>(hookup.TssPropChanged)), hookup => einfo.RemoveEventHandler(target, new EventHandler <EventArgs>(hookup.TssPropChanged)), para); AddHookupToRun(run, stringHookup); var propInfo = type.GetProperty(name); if (propInfo.CanWrite) { stringHookup.Writer = newVal => propInfo.SetValue(target, newVal, null); } } return(this); }
/// <summary> /// Given a function that fetches strings, a run which represents the initial value of that string /// already inserted into a particular paragraph box, and that we have identified the fetcher as /// a property with the specified name of the specified target object, but we have not been able to find /// a ''Name'Changed' event on the target object, this stub provides a possible place for a subclass to /// use an alternative strategy for hooking something up to notify the view of changes to the property. /// </summary> protected override void MakeHookupForString(Func <ITsString> fetcher, TssClientRun run, string name, object target, ParaBox para) { var cmObj = target as ICmObject; if (cmObj != null) { // Set up for PropChanged notification. RootFdo.DataAccess = cmObj.Cache.DomainDataByFlid; // ensures hooked up to receive PropChanged. Tuple <int, int> key = GetPropChangedKey(name, cmObj); var stringHookup = new TssHookup(target, fetcher, hookup => RootFdo.AddHookupToPropChanged(key, hookup), hookup => RootFdo.RemoveHookupFromPropChanged(key, hookup), para); stringHookup.Tag = key.Item2; AddHookupToRun(run, stringHookup); // Enhance JohnT: consider doing this by reflection. stringHookup.Writer = newVal => RootFdo.DataAccess.SetString(cmObj.Hvo, key.Item2, newVal); } }
public void HookupTsString() { MockData1 data1 = new MockData1(m_wsFrn, m_wsEng); data1.SimpleTwo = m_tsf.MakeString("foo", m_wsFrn); MockParaBox mockPara = new MockParaBox(); var mlHook = new TssHookup(MockData1Props.SimpleTwo(data1), mockPara); mlHook.ClientRunIndex = 5; data1.SimpleTwo = m_tsf.MakeString("bar", m_wsFrn); data1.RaiseSimpleTwoChanged(); Assert.AreEqual(5, mockPara.TheIndex, "Should have fired the event and notified the correct index"); Assert.AreEqual("bar", mockPara.TheTsString.Text, "Should have informed para of new string"); mlHook.Dispose(); }