Картинка блога

Теоретически, размеры экрана в приложения 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));

 }

}

Использование:

  1. Инициализируем модель как ресурс страницы:
  2. Пользуемся: 

Доступные значения понятны из кода.

Похожие статьи

    Нет похожих статей.