- Хроники. - -
WindowSizeAwareModel регируем на размер экрана в WinRT
Posted By Ikutsin On 18 марта 2013 @ 12:46 In .NET C# | Comments Disabled
[1]Теоретически, размеры экрана в приложения WinRT могут иметь неограниченный размер. Я встречал много горячих дискуссий, по поводу того, как лучше и как не стоит позиционировать элементы. Видел, что произойдет если ставить в Grid элементы не соблюдая общий делитель в размерах и как центровать холст, кода меняется ориентация экрана. Класс, показанный здесь, помогает реагировать на изменения размера экрана и получать «производные» размеры, зависящие от него.
Несмотря на то, что техника больше напоминает костыль, я успешно использую в нескольких проектах особенно для позиционирования элементов на холсте или получения относительных размеров (задать процент, в качестве размера, становится возможным). Прежде чем воспользоватся этим классом,
Ограничения, эту модель, нельзя использовать в стилях или прописывать как ресурс приложения, так как их инициализация происходит до инициализации окна — объекта 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));
}
}
Доступные значения понятны из кода.
Article printed from Хроники.:
URL to article: /2420-windowsizeawaremodel-regiruem-na-razmer-ekrana-v-winrt
URLs in this post:
[1] Image: /wp-content/uploads/2013/03/lollypop.jpg
Click here to print.
Copyright © 2008 Все, что меня окружает. All rights reserved.