Fix AspectRatioTrigger

This commit is contained in:
Jérôme Laban 2019-05-17 10:53:10 -04:00
commit 8559c576d6

View file

@ -14,126 +14,146 @@ using Windows.UI.Xaml;
namespace CalculatorApp.Views.StateTriggers namespace CalculatorApp.Views.StateTriggers
{ {
public enum Aspect public enum Aspect
{ {
Height, Height,
Width Width
} }
public sealed class AspectRatioTrigger : Windows.UI.Xaml.StateTriggerBase public sealed class AspectRatioTrigger : Windows.UI.Xaml.StateTriggerBase
{ {
/* The source for which this class will respond to size changed events. */ /* The source for which this class will respond to size changed events. */
public FrameworkElement Source public FrameworkElement Source
{ {
get { return (FrameworkElement)GetValue(SourceProperty); } get { return (FrameworkElement)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); } set { SetValue(SourceProperty, value); }
} }
public static readonly DependencyProperty SourceProperty = public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(FrameworkElement), typeof(AspectRatioTrigger), new PropertyMetadata(null)); DependencyProperty.Register(
name: nameof(Source),
propertyType: typeof(FrameworkElement),
ownerType: typeof(AspectRatioTrigger),
typeMetadata: new PropertyMetadata(
defaultValue: null,
propertyChangedCallback: (s, e) => (s as AspectRatioTrigger)?.OnSourcePropertyChanged(e.OldValue as FrameworkElement, e.NewValue as FrameworkElement))
);
/* Either Height or Width. The property will determine which aspect is used as the numerator when calculating /* Either Height or Width. The property will determine which aspect is used as the numerator when calculating
the aspect ratio. */ the aspect ratio. */
public Aspect NumeratorAspect public Aspect NumeratorAspect
{ {
get { return (Aspect)GetValue(NumeratorAspectProperty); } get { return (Aspect)GetValue(NumeratorAspectProperty); }
set { SetValue(NumeratorAspectProperty, value); } set { SetValue(NumeratorAspectProperty, value); }
} }
// Using a DependencyProperty as the backing store for NumeratorAspect. This enables animation, styling, binding, etc... // Using a DependencyProperty as the backing store for NumeratorAspect. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NumeratorAspectProperty = public static readonly DependencyProperty NumeratorAspectProperty =
DependencyProperty.Register("NumeratorAspect", typeof(Aspect), typeof(AspectRatioTrigger), new PropertyMetadata(Aspect.Height)); DependencyProperty.Register(
name: "NumeratorAspect",
propertyType: typeof(Aspect),
ownerType: typeof(AspectRatioTrigger),
typeMetadata: new PropertyMetadata(Aspect.Height)
);
/* The threshold that will cause the trigger to fire when the aspect ratio exceeds this value. */ /* The threshold that will cause the trigger to fire when the aspect ratio exceeds this value. */
public double Threshold public double Threshold
{ {
get { return (double)GetValue(ThresholdProperty); } get { return (double)GetValue(ThresholdProperty); }
set { SetValue(ThresholdProperty, value); } set { SetValue(ThresholdProperty, value); }
} }
// Using a DependencyProperty as the backing store for Threshold. This enables animation, styling, binding, etc... // Using a DependencyProperty as the backing store for Threshold. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ThresholdProperty = public static readonly DependencyProperty ThresholdProperty =
DependencyProperty.Register("Threshold", typeof(double), typeof(AspectRatioTrigger), new PropertyMetadata(0.0)); DependencyProperty.Register(
name: "Threshold",
propertyType: typeof(double),
ownerType: typeof(AspectRatioTrigger),
typeMetadata: new PropertyMetadata(0.0)
);
/* If true, the trigger will fire if the aspect ratio is greater than or equal to the threshold. */
public bool ActiveIfEqual
{
get { return (bool)GetValue(ActiveIfEqualProperty); }
set { SetValue(ActiveIfEqualProperty, value); }
}
// Using a DependencyProperty as the backing store for ActiveIfEqual. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ActiveIfEqualProperty =
DependencyProperty.Register(
name: "ActiveIfEqual",
propertyType: typeof(bool),
ownerType: typeof(AspectRatioTrigger),
typeMetadata: new PropertyMetadata(false)
);
AspectRatioTrigger()
{
SetActive(false);
}
/* If true, the trigger will fire if the aspect ratio is greater than or equal to the threshold. */ void OnSourcePropertyChanged(FrameworkElement oldValue, FrameworkElement newValue)
public bool ActiveIfEqual {
{ UnregisterSizeChanged(oldValue);
get { return (bool)GetValue(ActiveIfEqualProperty); } RegisterSizeChanged(newValue);
set { SetValue(ActiveIfEqualProperty, value); } }
}
// Using a DependencyProperty as the backing store for ActiveIfEqual. This enables animation, styling, binding, etc... void RegisterSizeChanged(FrameworkElement element)
public static readonly DependencyProperty ActiveIfEqualProperty = {
DependencyProperty.Register("ActiveIfEqual", typeof(bool), typeof(AspectRatioTrigger), new PropertyMetadata(false)); if (element == null)
{
return;
}
if (element != Source)
{
UnregisterSizeChanged(Source);
}
AspectRatioTrigger() element.SizeChanged += OnSizeChanged;
{ }
SetActive(false);
}
void OnSourcePropertyChanged(FrameworkElement oldValue, FrameworkElement newValue) void UnregisterSizeChanged(FrameworkElement element)
{ {
UnregisterSizeChanged(oldValue); if (element != null)
RegisterSizeChanged(newValue); {
} element.SizeChanged -= OnSizeChanged;
}
}
void RegisterSizeChanged(FrameworkElement element) void OnSizeChanged(object sender, SizeChangedEventArgs e)
{ {
if (element == null) UpdateIsActive(e.NewSize);
{ }
return;
}
if (element != Source) void UpdateIsActive(Size sourceSize)
{ {
UnregisterSizeChanged(Source); double numerator, denominator;
} if (NumeratorAspect == Aspect.Height)
{
numerator = sourceSize.Height;
denominator = sourceSize.Width;
}
else
{
numerator = sourceSize.Width;
denominator = sourceSize.Height;
}
element.SizeChanged += OnSizeChanged; bool isActive = false;
} if (denominator > 0)
{
double ratio = numerator / denominator;
double threshold = Math.Abs(Threshold);
void UnregisterSizeChanged(FrameworkElement element) isActive = ((ratio > threshold) || (ActiveIfEqual && (ratio == threshold)));
{ }
if (element != null)
{
element.SizeChanged -= OnSizeChanged;
}
}
void OnSizeChanged(object sender, SizeChangedEventArgs e) SetActive(isActive);
{ }
UpdateIsActive(e.NewSize);
}
void UpdateIsActive(Size sourceSize) }
{
double numerator, denominator;
if (NumeratorAspect == Aspect.Height)
{
numerator = sourceSize.Height;
denominator = sourceSize.Width;
}
else
{
numerator = sourceSize.Width;
denominator = sourceSize.Height;
}
bool isActive = false;
if (denominator > 0)
{
double ratio = numerator / denominator;
double threshold = Math.Abs(Threshold);
isActive = ((ratio > threshold) || (ActiveIfEqual && (ratio == threshold)));
}
SetActive(isActive);
}
}
} }