关于开发独立分辨率应用的技巧

找到工作区测量并在代码中设置一些属性以便它可以绑定到xaml中的Control的边距或高度/宽度属性是一个好习惯吗?

我这样做是为了让我的窗口根据可用的工作区resize。

const int w = SystemParameters.WorkArea.Width; const int h = SystemParameters.WorkArea.Height; public Thickness OuterGridMargin { get; } MainViewModel() { OuterGridMargin = new Thickness(w/5,h/6,w/5,h/4); } 

XAML:

  

我为一些外部容器执行此操作,以便布局不会以较低的分辨率混淆。 目前我在20英寸的1600×900 res(96 dpi)下工作。我的应用程序是小工具,没有常规窗口。

我想知道是否有一些替代方法。

搜索[wpf]分辨率] 1提出了许多解决类似问题的问题,但我仍然陷入困境,无法得出如何实现良好的分辨率无关布局的结论。

有两种方法可以处理WPF中的解决方案。

一种选择是设计到最小分辨率,并确保所有内容都适当停靠,以便随着窗口分辨率变大,元素变大。 这就是WinForms中有多少人做过的事情,并且仍然可以很好地用于WPF。 您可能已经有了一些如何通过设置Horizo​​ntalAlignment,VerticalAlignment和margin来处理这个问题的概念。

在WPF中做的更新,更时髦的事情在WinForms中几乎是不可能的,因为你的应用程序实际上只是放大,所以你的控件会像你的Window那样变大。 为此,您将在Window中的某个根元素上应用ScaleTransform,让WPF处理其余部分。 这真的很酷。

为了展示这是什么样的,这是一个窗口在你启动应用程序时的样子,使它变小,并使其更大: http : //i.stack.imgur.com/QeoVK.png

这是我制作的小样本应用程序的代码隐藏:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } #region ScaleValue Depdency Property public static readonly DependencyProperty ScaleValueProperty = DependencyProperty.Register("ScaleValue", typeof(double), typeof(MainWindow), new UIPropertyMetadata(1.0, new PropertyChangedCallback(OnScaleValueChanged), new CoerceValueCallback(OnCoerceScaleValue))); private static object OnCoerceScaleValue(DependencyObject o, object value) { MainWindow mainWindow = o as MainWindow; if (mainWindow != null) return mainWindow.OnCoerceScaleValue((double)value); else return value; } private static void OnScaleValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { MainWindow mainWindow = o as MainWindow; if (mainWindow != null) mainWindow.OnScaleValueChanged((double)e.OldValue, (double)e.NewValue); } protected virtual double OnCoerceScaleValue(double value) { if (double.IsNaN(value)) return 1.0f; value = Math.Max(0.1, value); return value; } protected virtual void OnScaleValueChanged(double oldValue, double newValue) { } public double ScaleValue { get { return (double)GetValue(ScaleValueProperty); } set { SetValue(ScaleValueProperty, value); } } #endregion private void MainGrid_SizeChanged(object sender, EventArgs e) { CalculateScale(); } private void CalculateScale() { double yScale = ActualHeight / 250f; double xScale = ActualWidth / 200f; double value = Math.Min(xScale, yScale); ScaleValue = (double)OnCoerceScaleValue(myMainWindow, value); } } 

和XAML:

           

JacobJ给出了很好的答案,我试了一下,它完美无缺。

对于任何有兴趣的人,我做了一个附加的行为,做同样的事情。 我还添加了从XAML指定宽度/高度分母的选项。 它可以像这样使用

    

ScaleToWindowSizeBehavior

 public static class ScaleToWindowSizeBehavior { #region ParentWindow public static readonly DependencyProperty ParentWindowProperty = DependencyProperty.RegisterAttached("ParentWindow", typeof(Window), typeof(ScaleToWindowSizeBehavior), new FrameworkPropertyMetadata(null, OnParentWindowChanged)); public static void SetParentWindow(FrameworkElement element, Window value) { element.SetValue(ParentWindowProperty, value); } public static Window GetParentWindow(FrameworkElement element) { return (Window)element.GetValue(ParentWindowProperty); } private static void OnParentWindowChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { FrameworkElement mainElement = target as FrameworkElement; Window window = e.NewValue as Window; ScaleTransform scaleTransform = new ScaleTransform(); scaleTransform.CenterX = 0; scaleTransform.CenterY= 0; Binding scaleValueBinding = new Binding { Source = window, Path = new PropertyPath(ScaleValueProperty) }; BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleXProperty, scaleValueBinding); BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleYProperty, scaleValueBinding); mainElement.LayoutTransform = scaleTransform; mainElement.SizeChanged += mainElement_SizeChanged; } #endregion // ParentWindow #region ScaleValue public static readonly DependencyProperty ScaleValueProperty = DependencyProperty.RegisterAttached("ScaleValue", typeof(double), typeof(ScaleToWindowSizeBehavior), new UIPropertyMetadata(1.0, OnScaleValueChanged, OnCoerceScaleValue)); public static double GetScaleValue(DependencyObject target) { return (double)target.GetValue(ScaleValueProperty); } public static void SetScaleValue(DependencyObject target, double value) { target.SetValue(ScaleValueProperty, value); } private static void OnScaleValueChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { } private static object OnCoerceScaleValue(DependencyObject d, object baseValue) { if (baseValue is double) { double value = (double)baseValue; if (double.IsNaN(value)) { return 1.0f; } value = Math.Max(0.1, value); return value; } return 1.0f; } private static void mainElement_SizeChanged(object sender, SizeChangedEventArgs e) { FrameworkElement mainElement = sender as FrameworkElement; Window window = GetParentWindow(mainElement); CalculateScale(window); } private static void CalculateScale(Window window) { Size denominators = GetDenominators(window); double xScale = window.ActualWidth / denominators.Width; double yScale = window.ActualHeight / denominators.Height; double value = Math.Min(xScale, yScale); SetScaleValue(window, value); } #endregion // ScaleValue #region Denominators public static readonly DependencyProperty DenominatorsProperty = DependencyProperty.RegisterAttached("Denominators", typeof(Size), typeof(ScaleToWindowSizeBehavior), new UIPropertyMetadata(new Size(1000.0, 700.0))); public static Size GetDenominators(DependencyObject target) { return (Size)target.GetValue(DenominatorsProperty); } public static void SetDenominators(DependencyObject target, Size value) { target.SetValue(DenominatorsProperty, value); } #endregion // Denominators } 

Fredrik Hedblad答案的小修正:

因为您在Grid元素中设置了DependencyProperty“Denominators”:

   

你必须使用网格调用GetDominator方法。 代替:

 private static void CalculateScale(Window window) { Size denominators = GetDenominators(window); 

你必须使用这样的东西:

 private static void mainElement_SizeChanged(object sender, SizeChangedEventArgs e) { FrameworkElement mainElement = sender as FrameworkElement; Window window = GetParentWindow(mainElement); CalculateScale(window, mainElement); } private static void CalculateScale(Window window, FrameworkElement mainElement) { Size denominators = GetDenominators(mainElement);