static bool ShouldIntercept(Control control, global::Windows.UI.Xaml.VisualState state, string stateName) { if (state == null || state.Name == "Normal") { // We don't intercept the "Normal" state, that's the base state onto which Forms applies properties return(false); } // Retrieve the VisualElement we're managing states for var visualElement = GetFormsElement(control); if (visualElement == null) { return(false); } // Retrieve the set of VisualStateGroups for the VisualElement var groups = VisualStateManager.GetVisualStateGroups(visualElement); if (groups == null) { // No groups? // Then the user disabled legacy color management through the platform specific, not by using the XFVSM // So our ignored states lists is effectively "Disabled" and "Focused" if (state.Name == "Disabled" || state.Name == "Focused") { return(true); } } else { // Check the states the XFVSM is managing foreach (VisualStateGroup vsg in groups) { foreach (VisualState vs in vsg.States) { if (vs.Name == stateName) { // The XFVSM is already handling this state, so don't let the Windows VSM do it return(true); } } } } return(false); }
// For most of the UWP controls, this custom VisualStateManager is injected to prevent the default Windows // VSM from handling states which the Forms VSM is already managing. // The exception are the controls which are built on TextBox (SearchBar, Entry, Editor); there's a UWP // bug wherein the GoToStateCore override for those controls is never called (Item 10976357 in VSTS) // So until that's resolved, the FormsTextBox control is doing that work as best it can. protected override bool GoToStateCore(Control control, FrameworkElement templateRoot, string stateName, global::Windows.UI.Xaml.VisualStateGroup @group, global::Windows.UI.Xaml.VisualState state, bool useTransitions) { // If this custom VSM is in play, it's because the control is using the Forms VSM or the user has disabled // legacy color handling. Either way, we may need to prevent the Windows VSM from transitioning to the new // state. So we intercept the transition here. if (ShouldIntercept(control, state, stateName)) { return(false); } return(base.GoToStateCore(control, templateRoot, stateName, @group, state, useTransitions)); }
void UpdateOnColor() { if (!(Cell is SwitchCell switchCell)) { return; } var color = switchCell.OnColor == Color.Default ? _defaultOnColor : new SolidColorBrush(switchCell.OnColor.ToWindowsColor()); var nativeSwitch = FrameworkElementExtensions.GetFirstDescendant <ToggleSwitch>(this); // change fill color in switch rectangle var rects = nativeSwitch.GetDescendantsByName <global::Windows.UI.Xaml.Shapes.Rectangle>("SwitchKnobBounds"); foreach (var rect in rects) { rect.Fill = color; } // change color in animation on PointerOver var grid = nativeSwitch.GetFirstDescendant <global::Windows.UI.Xaml.Controls.Grid>(); var gridVisualStateGroups = global::Windows.UI.Xaml.VisualStateManager.GetVisualStateGroups(grid); global::Windows.UI.Xaml.VisualStateGroup vsGroup = null; foreach (var visualGroup in gridVisualStateGroups) { if (visualGroup.Name == "CommonStates") { vsGroup = visualGroup; break; } } if (vsGroup == null) { return; } global::Windows.UI.Xaml.VisualState vState = null; foreach (var visualState in vsGroup.States) { if (visualState.Name == "PointerOver") { vState = visualState; break; } } if (vState == null) { return; } var visualStates = vState.Storyboard.Children; foreach (ObjectAnimationUsingKeyFrames item in visualStates) { if ((string)item.GetValue(Storyboard.TargetNameProperty) == "SwitchKnobBounds") { item.KeyFrames[0].Value = color; break; } } }