2010-07-07 20 views
18

Workarea ölçümünü bulmak ve bazı özellikleri, Denetimin kenar boşluğuna veya xaml'deki yükseklik/Genişlik özelliklerine bağlı olacak şekilde ayarlamak iyi bir uygulamadır mı?çözünürlük, bağımsız uygulama geliştirme hakkında ipuçları

Bunu yapmak için penceremin kullanılabilir çalışma alanına göre yeniden boyutlandırılmasını sağlayın.

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: düzen düşük çözünürlüklerde haberci olmaz ki

<Grid Margin="{Binding OuterGridMargin}" /> 

bu bazı dış kapları için yapıyorum. Şu anda bir 20" içinde 1600x900 res (96 dpi) çalışıyorum. Başvurum gibi alet ve düzenli penceresi yoktur.

Ben bazı alternatif yaklaşımlar vardır olmadığını bilmek istiyorum.

bir arama [wpf] resolution] 1 benzer bir soruna hitap eden bir çok soruya yol açıyor ama yine de takılıyorum ve iyi bir çözünürlükten bağımsız bir düzen elde etmek için bir sonuca ulaşamıyorum.

cevap

42

Çözünürlükle başa çıkmanın iki yolu var. WPF içinde

Bir seçenek en az çözünürlüğe tasarım yapmak ve sadece arifesinde emin olun rything uygun şekilde yerleştirilmiştir, böylece Pencere çözünürlüğü büyüdükçe elemanlar büyür. Bu, WinForms'ta birçok insanın yaptığı şeydi ve hala WPF için gayet iyi çalışıyor. Muhtemelen HorizontalAlignment, VerticalAlignment ve marjları ayarlayarak bununla nasıl başa çıkacağınıza dair bazı konseptleriniz vardır.

WFF'de WinForms uygulamasında yapılması neredeyse imkansız olan daha yeni, daha önemli olan şey, uygulamanızın yalnızca yakınlaştırmasını sağlamaktır; Bunu yapmak için, Pencerenizdeki bazı kök öğeleri üzerinde bir ScaleTransform uygulayacak ve WPF'nin gerisini halledmesine izin vereceksiniz. Bu gerçekten havalı. Bu burada, böyle bir pencere küçültmezse Uygulamayı başlatın ve daha büyük yaparken nasıl görüneceğini ne göstermek için

: Burada http://i.stack.imgur.com/QeoVK.png

kod arkasında yaptığım küçük bir örnek uygulaması için :

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); 
    } 
} 

Ve XAML:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    Name="myMainWindow" 
    Width="200" Height="250"> 
<Grid Name="MainGrid" SizeChanged="MainGrid_SizeChanged"> 
    <Grid.LayoutTransform> 
     <ScaleTransform x:Name="ApplicationScaleTransform" 
         CenterX="0" 
         CenterY="0" 
         ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}" 
         ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}" /> 
    </Grid.LayoutTransform> 
    <Grid VerticalAlignment="Center" HorizontalAlignment="Center" Height="150"> 
     <TextBlock FontSize="20" Text="Hello World" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center"/> 
     <Button Content="Button" VerticalAlignment="Bottom" HorizontalAlignment="Center"/> 
    </Grid> 
</Grid> 

+0

Büyük cevabı:

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

Böyle bir şey kullanmalısınız! Çok detaylı. Sadelik, netlik ve tamlık için –

+0

+1, adil görünmüyor. – Arjang

+0

Aynı efekti elde etmek için her şeyi bir Viewbox içine koyabilirsiniz. – Surfbutler

12

JacobJ tarafından büyük cevap, ben denedim ve mükemmel çalıştı.

İlgilenen herkes için aynı şeyi yapan eklenmiş bir davranış yaptım. Ayrıca XAML'den genişlik/yükseklik paydalarını belirtme seçeneğini ekledim.Bu Fredrik Hedblad verilen yanıta bu

<Grid Name="MainGrid" 
     inf:ScaleToWindowSizeBehavior.Denominators="1000, 700" 
     inf:ScaleToWindowSizeBehavior.ParentWindow="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> 
    <!--...--> 
</Grid> 

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 
} 
+0

Cevabınız çok ilginç görünüyor, ancak XAML ve C# 'da çalışmasına izin vermek için hala çok kötüyüm. XAML bölümünde "inf:" kullanımı eksik ... –

+0

@AndreaAntonangeli 'inf:' AttachedProperty'yi kullanmadan önce bildirilen bir ad alanı, yani 'xmlns: inf = 'clr-namespace: My. '" App.AttachedProps. – jv42

0

Küçük düzeltme gibi kullanılabilir:

Eğer Izgara öğesi DependencyProperty "paydalar" ayarlama nedeniyle:

<Grid Name="MainGrid" 
     inf:ScaleToWindowSizeBehavior.Denominators="1000, 700" 
    <!--...--> 
</Grid> 

y ızgarayı kullanarak GetDominator yöntemini çağırmalısınız. yerine:

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); 
İlgili konular