/// <summary> /// override of WriteDynamicEvent /// </summary> public override void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { bool isStyleEvent = (xamlClrEventNode.IsStyleSetterEvent || xamlClrEventNode.IsTemplateEvent); bool localEvent = _compiler.LocalAssembly == xamlClrEventNode.EventMember.ReflectedType.Assembly; if (isStyleEvent) { if (localEvent) { // validate the event handler name per CLS grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); xamlClrEventNode.LocalAssemblyName = _compiler.AssemblyName; // Pass2 should always be true here as otherwise localEvent will be false, but just being paranoid here. if (_pass2) { XamlTypeMapper.HasInternals = true; } } else { if (!xamlClrEventNode.IsSameScope) { _connectionId++; } xamlClrEventNode.ConnectionId = _connectionId; if (!_pass2) { _compiler.ConnectStyleEvent(xamlClrEventNode); } } return; } bool appEvent = KnownTypes.Types[(int)KnownElements.Application].IsAssignableFrom(xamlClrEventNode.EventMember.DeclaringType); if (!appEvent) { if (!_pass2) { // validate the event handler name per CLS grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); if (_events == null) { _events = new ArrayList(); } _events.Add(new MarkupCompiler.MarkupEventInfo(xamlClrEventNode.Value, xamlClrEventNode.EventName, xamlClrEventNode.EventMember, xamlClrEventNode.LineNumber)); } // if not local event ... if (!localEvent) { WriteConnectionId(); } } else if (!_pass2) { // Since Application is not an Element it doesn't implement IComponentConnector and // so needs to add events directly. MarkupCompiler.MarkupEventInfo mei = new MarkupCompiler.MarkupEventInfo(xamlClrEventNode.Value, xamlClrEventNode.EventName, xamlClrEventNode.EventMember, xamlClrEventNode.LineNumber); _compiler.AddApplicationEvent(mei); } if (_pass2) { // if local event, add Baml Attribute Record for local event if (localEvent) { // validate the event handler name per C# grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); XamlPropertyNode xamlPropertyNode = new XamlPropertyNode(xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth, xamlClrEventNode.EventMember, _compiler.AssemblyName, xamlClrEventNode.EventMember.ReflectedType.FullName, xamlClrEventNode.EventName, xamlClrEventNode.Value, BamlAttributeUsage.Default, false); XamlTypeMapper.HasInternals = true; base.WriteProperty(xamlPropertyNode); } } }
/// <summary> /// Write an Event Connector and call the controlling compiler parser to generate event hookup code. /// </summary> public override void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { if (_previousXamlParser != null) { Debug.Assert(_styleModeStack.Mode == StyleMode.VisualTree); // if this event token is not owned by this TemplateXamlParser, then just chain // the WriteClrEvent call to the controlling parser. Ulimately, this will // reach the markup compiler that will deal with this info as appropriate. bool isOriginatingEvent = xamlClrEventNode.IsOriginatingEvent; if (isOriginatingEvent) { // set up additional state on event node for the markup compiler to use. Debug.Assert(!xamlClrEventNode.IsStyleSetterEvent); xamlClrEventNode.IsTemplateEvent = true; xamlClrEventNode.IsSameScope = _isSameScope; // any intermediary controlling parsers need to get out of the way so that // the markup compiler can ultimately do its thing. xamlClrEventNode.IsOriginatingEvent = false; // Store away the type of the element we're currently in. E.g. // in <Button Click="OnClicked"/>, this will be typeof(Button). // In the case of regular CLR events, this type is the same as that // which can be found in xamlClrEventNode.EventMember. But in the // case of attached events, EventMember is the class that holds // the attached event, and the compiler needs to know the type of // the listener. xamlClrEventNode.ListenerType = (Type) _elementTypeStack.Peek(); } _previousXamlParser.WriteClrEvent(xamlClrEventNode); if (isOriginatingEvent) { if (!String.IsNullOrEmpty(xamlClrEventNode.LocalAssemblyName)) { // if this event is a local event need to generate baml for it now XamlPropertyNode xamlPropertyNode = new XamlPropertyNode(xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth, null, xamlClrEventNode.LocalAssemblyName, xamlClrEventNode.EventMember.ReflectedType.FullName, xamlClrEventNode.EventName, xamlClrEventNode.Value, BamlAttributeUsage.Default, false); base.WriteProperty(xamlPropertyNode); } else { // write out a connectionId to the baml stream only if a // new event scope was encountered if (!_isSameScope) { base.WriteConnectionId(xamlClrEventNode.ConnectionId); } // We have just finished processing the start of a new event scope. // So specifiy start of this new scope. _isSameScope = true; } } } }
internal void ConnectStyleEvent(XamlClrEventNode xamlClrEventNode) { CodeConditionStatement ccsConnector = null; // validate the event handler name per C# grammar for identifiers ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); EnsureStyleConnector(); if (!xamlClrEventNode.IsSameScope) { int connectionId = xamlClrEventNode.ConnectionId; if (SwitchStatementSupported()) { // break any previous case staements as we are starting a new connection scope. if (_ccRoot.StyleConnectorFn.Statements.Count > 1) { CodeSnippetStatement cssBreak = new CodeSnippetStatement(BREAK_STATEMENT); _ccRoot.StyleConnectorFn.Statements.Add(cssBreak); } // case 1: // CodeSnippetStatement cssCase = new CodeSnippetStatement(CASE_STATEMENT + connectionId + COLON); _ccRoot.StyleConnectorFn.Statements.Add(cssCase); } else { // if (connectionId == 1) // ccsConnector = new CodeConditionStatement(); ccsConnector.Condition = new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CONNECTIONID), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(connectionId)); } } else if (!SwitchStatementSupported()) { // if in the same scope then use the if statement that was last generated // at the start of the scope Debug.Assert(_ccRoot.StyleConnectorFn.Statements.Count > 0); ccsConnector = _ccRoot.StyleConnectorFn.Statements[_ccRoot.StyleConnectorFn.Statements.Count - 1] as CodeConditionStatement; Debug.Assert(ccsConnector != null); } CodeArgumentReferenceExpression careTarget = new CodeArgumentReferenceExpression(TARGET); if (xamlClrEventNode.IsStyleSetterEvent) { // EventSetter declaration only once to avoid warning! if (!_hasEmittedEventSetterDeclaration) { _hasEmittedEventSetterDeclaration = true; // EventSetter eventSetter; // CodeVariableDeclarationStatement cvdsES = new CodeVariableDeclarationStatement(KnownTypes.Types[(int)KnownElements.EventSetter], EVENTSETTER); _ccRoot.StyleConnectorFn.Statements.Insert(0, cvdsES); } // eventSetter = new EventSetter(); // CodeExpression[] esParams = {}; CodeVariableReferenceExpression cvreES = new CodeVariableReferenceExpression(EVENTSETTER); CodeAssignStatement casES = new CodeAssignStatement(cvreES, new CodeObjectCreateExpression(KnownTypes.Types[(int)KnownElements.EventSetter], esParams)); // eventSetter.Event = Button.ClickEvent; // CodePropertyReferenceExpression cpreEvent = new CodePropertyReferenceExpression(cvreES, EVENT); CodeAssignStatement casEvent = new CodeAssignStatement(cpreEvent, GetEvent(xamlClrEventNode.EventMember, xamlClrEventNode.EventName, xamlClrEventNode.Value)); // eventSetter.Handler = new RoutedEventHandler(OnClick); // CodePropertyReferenceExpression cpreHandler = new CodePropertyReferenceExpression(cvreES, HANDLER); CodeAssignStatement casHandler = new CodeAssignStatement(cpreHandler, GetEventDelegate(null, xamlClrEventNode.EventMember, xamlClrEventNode.EventName, xamlClrEventNode.Value)); AddLinePragma(casHandler, xamlClrEventNode.LineNumber); // ((Style)target).Setters.Add(eventSetter); // CodeCastExpression cceTarget = new CodeCastExpression(KnownTypes.Types[(int)KnownElements.Style], careTarget); CodePropertyReferenceExpression cpreSetters = new CodePropertyReferenceExpression(cceTarget, SETTERS); CodeMethodInvokeExpression cmieAdd = new CodeMethodInvokeExpression(cpreSetters, ADD, cvreES); if (SwitchStatementSupported()) { _ccRoot.StyleConnectorFn.Statements.Add(casES); _ccRoot.StyleConnectorFn.Statements.Add(casEvent); _ccRoot.StyleConnectorFn.Statements.Add(casHandler); _ccRoot.StyleConnectorFn.Statements.Add(new CodeExpressionStatement(cmieAdd)); } else { ccsConnector.TrueStatements.Add(casES); ccsConnector.TrueStatements.Add(casEvent); ccsConnector.TrueStatements.Add(casHandler); ccsConnector.TrueStatements.Add(new CodeExpressionStatement(cmieAdd)); // Only add if statement at start of new scope if (!xamlClrEventNode.IsSameScope) { _ccRoot.StyleConnectorFn.Statements.Add(ccsConnector); } } } else { // // ((Foo)target).Bar += new BarEventHandler(OnBar); // // *or* // // ((Foo)target).AddHandler( Baz.BarEvent, new BarEventHandler(OnBar)); // CodeCastExpression cceTarget; Type eventTarget; // Create the markup event information MarkupEventInfo mei = new MarkupEventInfo( xamlClrEventNode.Value, // Event handler string xamlClrEventNode.EventName, // Event name string xamlClrEventNode.EventMember, // MemberInfo xamlClrEventNode.LineNumber); // LineNumber // Get the type that defines the event (e.g. typeof(Button) for Button.Clicked or typeof(Mouse) for Mouse.MouseMove) eventTarget = xamlClrEventNode.ListenerType; // Create the type cast expression "(Foo)target" cceTarget = new CodeCastExpression( eventTarget, careTarget); // Create the whole code statement (either in += form or in AddHandler form) CodeStatement csAddCLREvent = AddCLREvent( eventTarget, null, cceTarget, mei ); if (SwitchStatementSupported()) { _ccRoot.StyleConnectorFn.Statements.Add( csAddCLREvent ); } else { ccsConnector.TrueStatements.Add( csAddCLREvent ); // Only add if statement at start of new scope if (!xamlClrEventNode.IsSameScope) { _ccRoot.StyleConnectorFn.Statements.Add(ccsConnector); } } } }
/// <summary> /// override of WriteDynamicEvent /// </summary> public override void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { bool isStyleEvent = (xamlClrEventNode.IsStyleSetterEvent || xamlClrEventNode.IsTemplateEvent); bool localEvent = _compiler.LocalAssembly == xamlClrEventNode.EventMember.ReflectedType.Assembly; if (isStyleEvent) { if (localEvent) { // validate the event handler name per CLS grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); xamlClrEventNode.LocalAssemblyName = _compiler.AssemblyName; // Pass2 should always be true here as otherwise localEvent will be false, but just being paranoid here. if (_pass2) { XamlTypeMapper.HasInternals = true; } } else { if (!xamlClrEventNode.IsSameScope) { _connectionId++; } xamlClrEventNode.ConnectionId = _connectionId; if (!_pass2) { _compiler.ConnectStyleEvent(xamlClrEventNode); } } return; } bool appEvent = KnownTypes.Types[(int)KnownElements.Application].IsAssignableFrom(xamlClrEventNode.EventMember.DeclaringType); if (!appEvent) { if (!_pass2) { // validate the event handler name per CLS grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); if (_events == null) _events = new ArrayList(); _events.Add(new MarkupCompiler.MarkupEventInfo(xamlClrEventNode.Value, xamlClrEventNode.EventName, xamlClrEventNode.EventMember, xamlClrEventNode.LineNumber)); } // if not local event ... if (!localEvent) { WriteConnectionId(); } } else if (!_pass2) { // Since Application is not an Element it doesn't implement IComponentConnector and // so needs to add events directly. MarkupCompiler.MarkupEventInfo mei = new MarkupCompiler.MarkupEventInfo(xamlClrEventNode.Value, xamlClrEventNode.EventName, xamlClrEventNode.EventMember, xamlClrEventNode.LineNumber); _compiler.AddApplicationEvent(mei); } if (_pass2) { // if local event, add Baml Attribute Record for local event if (localEvent) { // validate the event handler name per C# grammar for identifiers _compiler.ValidateEventHandlerName(xamlClrEventNode.EventName, xamlClrEventNode.Value); XamlPropertyNode xamlPropertyNode = new XamlPropertyNode(xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth, xamlClrEventNode.EventMember, _compiler.AssemblyName, xamlClrEventNode.EventMember.ReflectedType.FullName, xamlClrEventNode.EventName, xamlClrEventNode.Value, BamlAttributeUsage.Default, false); XamlTypeMapper.HasInternals = true; base.WriteProperty(xamlPropertyNode); } } }
/// <summary> /// Write out the Clr event. /// </summary> public virtual void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { // Parser currently doesn't support hooking up Events directly from // XAML so throw an exception. In the compile case this method // is overriden. if (null == ParserHooks) { ThrowException(SRID.ParserNoEvents, xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition); } else if (BamlRecordWriter != null) { BamlRecordWriter.WriteClrEvent(xamlClrEventNode); } }
internal void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { // This should have been overridden by AC to catch the CLR event case before // this point is reached. If not it means we have a designer which // should have been given the pertinent information, so keep this as a placeholder, // but don't do anything now. }
private void ProcessEventSetterNode(XamlEndAttributesNode xamlEndAttributesNode) { // Check for EventSetter properties. These aren't really stored as properties but // resolved at the EventSetter end tag as events by the compiler Debug.Assert(_inEventSetter); string member = _event; MemberInfo memberInfo = GetPropertyOrEventInfo(xamlEndAttributesNode, ref member); // If we have an event setter on a locally defined component, write it out // as a property instead of an event so that it will be resolved at runtime. if (null != memberInfo) { XamlClrEventNode eventNode = new XamlClrEventNode( xamlEndAttributesNode.LineNumber, xamlEndAttributesNode.LinePosition, xamlEndAttributesNode.Depth, member, memberInfo, _handler); #if HANDLEDEVENTSTOO eventNode.HandledEventsToo = _handledEventsToo; #endif WriteClrEvent(eventNode); } _event = null; _handler = null; #if HANDLEDEVENTSTOO _handledEventsToo = false; #endif }
/// <summary> /// Write an Event Connector and call the controlling compiler parser to generate event hookup code. /// </summary> public override void WriteClrEvent(XamlClrEventNode xamlClrEventNode) { if (_previousXamlParser != null) { if (_styleModeStack.Mode != StyleMode.Setters) { ThrowException(SRID.StyleTargetNoEvents, xamlClrEventNode.EventName, xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition); } // if this event token is not owned by this StyleXamlParser, then just chain // the WriteClrEvent call to the controlling parser. Ulimately, this will // reach the markup compiler that will deal with this info as appropriate. bool isOriginatingEvent = xamlClrEventNode.IsOriginatingEvent; if (isOriginatingEvent) { // set up additional state on event node for the markup compiler to use. Debug.Assert(!xamlClrEventNode.IsTemplateEvent && _inEventSetter); xamlClrEventNode.IsStyleSetterEvent = _inEventSetter; xamlClrEventNode.IsSameScope = _isSameScope; // any intermediary controlling parsers need to get out of the way so that // the markup compiler can ultimately do its thing. xamlClrEventNode.IsOriginatingEvent = false; } _previousXamlParser.WriteClrEvent(xamlClrEventNode); if (isOriginatingEvent) { if (!String.IsNullOrEmpty(xamlClrEventNode.LocalAssemblyName)) { // if this event is a local event need to generate baml for it now string assemblyName = KnownTypes.Types[(int)KnownElements.EventSetter].Assembly.FullName; base.WriteElementStart(new XamlElementStartNode(XamlNodeType.ElementStart, xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth, assemblyName, KnownTypes.Types[(int)KnownElements.EventSetter].FullName, KnownTypes.Types[(int)KnownElements.EventSetter], null /*serializerType*/, false /*isEmptyElement*/, false /*needsDictionaryKey*/, false /*isInjected*/)); XamlPropertyNode xamlPropertyNode = new XamlPropertyNode(xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth, null, xamlClrEventNode.LocalAssemblyName, xamlClrEventNode.EventMember.ReflectedType.FullName, xamlClrEventNode.EventName, xamlClrEventNode.Value, BamlAttributeUsage.Default, false); base.WriteProperty(xamlPropertyNode); base.WriteElementEnd(new XamlElementEndNode(xamlClrEventNode.LineNumber, xamlClrEventNode.LinePosition, xamlClrEventNode.Depth)); } else { // write out a connectionId to the baml stream only if a // new event scope was encountered if (!_isSameScope) { base.WriteConnectionId(xamlClrEventNode.ConnectionId); } // We have just finished processing the start of a new event scope. // So specifiy start of this new scope. _isSameScope = true; } } } }