Теоретически, размеры экрана в приложения WinRT могут иметь неограниченный размер. Я встречал много горячих дискуссий, по поводу того, как лучше и как не стоит позиционировать элементы. Видел, что произойдет если ставить в Grid элементы не соблюдая общий делитель в размерах и как центровать холст, кода меняется ориентация экрана. Класс, показанный здесь, помогает реагировать на изменения размера экрана и получать «производные» размеры, зависящие от него.
Несмотря на то, что техника больше напоминает костыль, я успешно использую в нескольких проектах особенно для позиционирования элементов на холсте или получения относительных размеров (задать процент, в качестве размера, становится возможным). Прежде чем воспользоватся этим классом,
- Убедитесь что вашу задачу нельзя решить штатными средствами (во многих случаях это не так)
- Убедитесь что использование не противоречит указаниям и рекомендациям от Microsoft. Я бы, например не советовал менять размер шрифта в зависимоти от размера окна.
Ограничения, эту модель, нельзя использовать в стилях или прописывать как ресурс приложения, так как их инициализация происходит до инициализации окна — объекта Window. Теперь, собственно сам класс:
public class WindowSizeAwareModel : INotifyPropertyChanged { private readonly int _baseWidth; private readonly int _baseHeight; public WindowSizeAwareModel(int baseWidth, int baseHeight) { _baseWidth = baseWidth; _baseHeight = baseHeight; Window.Current.SizeChanged += Current_SizeChanged; Func<double, double=""> multiply = (s, i) => s * i; //Func<double, double=""> divide = (s, i) => s / i; Func<double, double=""> minus = (s, i) => s - i; WidthAspect = new ResizeAwareModelRatio(() => ScaleWidth, multiply); HeightAspect = new ResizeAwareModelRatio(() => ScaleHeight, multiply); RatioAspect = new ResizeAwareModelRatio(() => WindowRatio, multiply); SizeAspect = new ResizeAwareModelRatio(() => ScaleSize, multiply); MarginAspect = new ResizeAwareModelThickness(this); WidthPercent = new ResizeAwareModelRatio(() => WindowWidth, multiply, 0.01); HeightPercent = new ResizeAwareModelRatio(() => WindowHeight, multiply, 0.01); WidthMinus = new ResizeAwareModelRatio(() => WindowHeight, minus); HeightMinus = new ResizeAwareModelRatio(() => WindowHeight, minus); } public class ResizeAwareModelThickness : INotifyPropertyChanged { private readonly WindowSizeAwareModel _model; public ResizeAwareModelThickness(WindowSizeAwareModel model) { _model = model; } [IndexerName("Item")] public Thickness this[double index] { get { return this[index.ToString()]; } } [IndexerName("Item")] public Thickness this[string index] { get { double[] values = { 0, 0, 0, 0 }; var input = index.Split(new[] { ' ', ',' }).Select(Double.Parse).ToArray(); for (int i = 0; i < values.Length; i++) { values[i] = input[i % input.Length] * (i % 2 == 0 ? _model.ScaleWidth : _model.ScaleHeight); } return new Thickness(values[0], values[1], values[2], values[3]); } } public void TriggerUpdate() { OnPropertyChanged("Item[]"); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } public class ResizeAwareModelRatio : INotifyPropertyChanged { private readonly Func<double> _scale; private readonly Func<double, double=""> _ratio; private readonly double _intFactor; public ResizeAwareModelRatio(Func<double> scale, Func<double, double=""> ratio, double intFactor =1.0) { _scale = scale; _ratio = ratio; _intFactor = intFactor; } public double this[double index] { get { return _ratio(_scale(), index); } } [IndexerName("Item")] public int this[int index] { get { return (int)(this[index * _intFactor]); } } public void TriggerUpdate() { OnPropertyChanged("Item"); OnPropertyChanged("Item[]"); OnPropertyChanged("Item[100]"); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } public override string ToString() { return String.Format("{0} {1} {2}", this[1.0], this[0.5], this[0]); } } private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e) { TriggerUpdate(); } private async void TriggerUpdate() { OnPropertyChanged("WindowWidth"); OnPropertyChanged("WindowHeight"); OnPropertyChanged("WindowPixels"); OnPropertyChanged("WindowRatio"); OnPropertyChanged("ApplicationViewState"); OnPropertyChanged("ScaleWidth"); OnPropertyChanged("ScaleHeight"); OnPropertyChanged("ScaleSize"); WidthAspect.TriggerUpdate(); HeightAspect.TriggerUpdate(); RatioAspect.TriggerUpdate(); SizeAspect.TriggerUpdate(); MarginAspect.TriggerUpdate(); WidthPercent.TriggerUpdate(); HeightPercent.TriggerUpdate(); WidthMinus.TriggerUpdate(); HeightMinus.TriggerUpdate(); } public ResizeAwareModelRatio WidthAspect { get; private set; } public ResizeAwareModelRatio HeightAspect { get; private set; } public ResizeAwareModelRatio RatioAspect { get; private set; } public ResizeAwareModelRatio SizeAspect { get; private set; } public ResizeAwareModelRatio WidthPercent { get; private set; } public ResizeAwareModelRatio HeightPercent { get; private set; } public ResizeAwareModelRatio WidthMinus { get; private set; } public ResizeAwareModelRatio HeightMinus { get; private set; } public ResizeAwareModelThickness MarginAspect { get; private set; } public double BaseWidth { get { return _baseWidth; } } public double BaseHeight { get { return _baseHeight; } } public double BaseRatio { get { return BaseWidth / BaseHeight; } } public double BasePixels { get { return BaseWidth * BaseHeight; } } public double WindowWidth { get { return Window.Current.Bounds.Width; } } public double WindowHeight { get { return Window.Current.Bounds.Height; } } public double WindowRatio { get { return WindowWidth / WindowHeight; } } public double WindowPixels { get { return WindowWidth * WindowHeight; } } public double ScaleWidth { get { return WindowWidth / BaseWidth; } } public double ScaleHeight { get { return WindowWidth / BaseHeight; } } public double ScaleSize { get { return WindowWidth / BaseWidth * WindowHeight / BaseHeight; } } public ApplicationViewState ApplicationViewState { get { return ApplicationView.Value; } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }
- Инициализируем модель как ресурс страницы:
- Пользуемся:
Доступные значения понятны из кода.
Похожие статьи
- Нет похожих статей.