void UpdateEnabled(double value) { double increment = Increment; if (_plus != null) { if (value + increment > Maximum) { _plusStateCache = PseudoDisable(_plus); } else { PsuedoEnable(_plus, ref _plusStateCache); } } if (_minus != null) { if (value - increment < Minimum) { _minusStateCache = PseudoDisable(_minus); } else { PsuedoEnable(_minus, ref _minusStateCache); } } }
/* * The below serves as a way to disable the button visually, rather than using IsEnabled. It's a hack * but should remain stable as long as the user doesn't change the WinRT Button template too much. * * The reason we're not using IsEnabled is that the buttons have a click radius that overlap about 40% * of the next button. This doesn't cause a problem until one button becomes disabled, then if you think * you're still hitting + (haven't noticed its disabled), you will actually hit -. This hack doesn't * completely solve the problem, but it drops the overlap to something like 20%. I haven't found the root * cause, so this will have to suffice for now. */ void PsuedoEnable(Control control, ref VisualStateCache cache) { if (cache == null || VisualTreeHelper.GetChildrenCount(control) == 0) { return; } var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0); IList <VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement); if (cache.FocusStates != null) { groups.Add(cache.FocusStates); } var commonStates = groups.FirstOrDefault(g => g.Name == "CommonStates"); if (commonStates == null) { return; } if (cache.Normal != null) { commonStates.States.Insert(0, cache.Normal); // defensive } if (cache.Pressed != null) { commonStates.States.Add(cache.Pressed); } if (cache.PointerOver != null) { commonStates.States.Add(cache.PointerOver); } VisualStateManager.GoToState(control, "Normal", true); cache = null; }
VisualStateCache PseudoDisable(Control control) { if (VisualTreeHelper.GetChildrenCount(control) == 0) { control.ApplyTemplate(); } VisualStateManager.GoToState(control, "Disabled", true); var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0); var cache = new VisualStateCache(); IList <VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement); VisualStateGroup common = null; foreach (var group in groups) { if (group.Name == "CommonStates") { common = group; } else if (group.Name == "FocusStates") { cache.FocusStates = group; } else if (cache.FocusStates != null && common != null) { break; } } if (cache.FocusStates != null) { groups.Remove(cache.FocusStates); } if (common != null) { foreach (VisualState state in common.States) { if (state.Name == "Normal") { cache.Normal = state; } else if (state.Name == "Pressed") { cache.Pressed = state; } else if (state.Name == "PointerOver") { cache.PointerOver = state; } } if (cache.Normal != null) { common.States.Remove(cache.Normal); } if (cache.Pressed != null) { common.States.Remove(cache.Pressed); } if (cache.PointerOver != null) { common.States.Remove(cache.PointerOver); } } return(cache); }
void UpdateEnabled(double value) { double increment = Increment; if (_plus != null) { if (value + increment > Maximum) _plusStateCache = PseudoDisable(_plus); else PsuedoEnable(_plus, ref _plusStateCache); } if (_minus != null) { if (value - increment < Minimum) _minusStateCache = PseudoDisable(_minus); else PsuedoEnable(_minus, ref _minusStateCache); } }
/* The below serves as a way to disable the button visually, rather than using IsEnabled. It's a hack but should remain stable as long as the user doesn't change the WinRT Button template too much. The reason we're not using IsEnabled is that the buttons have a click radius that overlap about 40% of the next button. This doesn't cause a problem until one button becomes disabled, then if you think you're still hitting + (haven't noticed its disabled), you will actually hit -. This hack doesn't completely solve the problem, but it drops the overlap to something like 20%. I haven't found the root cause, so this will have to suffice for now. */ void PsuedoEnable(Control control, ref VisualStateCache cache) { if (cache == null || VisualTreeHelper.GetChildrenCount(control) == 0) return; var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0); IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement); if (cache.FocusStates != null) groups.Add(cache.FocusStates); var commonStates = groups.FirstOrDefault(g => g.Name == "CommonStates"); if (commonStates == null) return; if (cache.Normal != null) commonStates.States.Insert(0, cache.Normal); // defensive if (cache.Pressed != null) commonStates.States.Add(cache.Pressed); if (cache.PointerOver != null) commonStates.States.Add(cache.PointerOver); VisualStateManager.GoToState(control, "Normal", true); cache = null; }
VisualStateCache PseudoDisable(Control control) { if (VisualTreeHelper.GetChildrenCount(control) == 0) control.ApplyTemplate(); VisualStateManager.GoToState(control, "Disabled", true); var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0); var cache = new VisualStateCache(); IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement); VisualStateGroup common = null; foreach (var group in groups) { if (group.Name == "CommonStates") common = group; else if (group.Name == "FocusStates") cache.FocusStates = group; else if (cache.FocusStates != null && common != null) break; } if (cache.FocusStates != null) groups.Remove(cache.FocusStates); if (common != null) { foreach (VisualState state in common.States) { if (state.Name == "Normal") cache.Normal = state; else if (state.Name == "Pressed") cache.Pressed = state; else if (state.Name == "PointerOver") cache.PointerOver = state; } if (cache.Normal != null) common.States.Remove(cache.Normal); if (cache.Pressed != null) common.States.Remove(cache.Pressed); if (cache.PointerOver != null) common.States.Remove(cache.PointerOver); } return cache; }