【问题标题】:Databinding to the width of a form数据绑定到表单的宽度
【发布时间】:2013-09-16 15:54:48
【问题描述】:

我正在尝试动态缩放基于 WPF 的应用程序的 UI,我想使用当前分辨率与本机分辨率的比率,如下所示:

    <Grid.LayoutTransform>
        <ScaleTransform CenterX="0" CenterY="0" ScaleX="{Binding FormWidth/NativeREsolution}" ScaleY="{Binding FormWidth/NativeREsolution}"/>
    </Grid.LayoutTransform>

我发现 scale transform 的原因是它会缩放容器内的所有 UI 元素,包括框架和子页面。

有没有办法做到这一点?

或者,有没有更好的方法可以根据窗口大小动态缩放应用程序?

【问题讨论】:

  • 什么?这是 WPF 吗?你真的不需要那个。这个问题没有足够的信息来提供答案。请澄清
  • 是的,它是 WPF,添加了标签并希望添加足够多。我需要的是在调整应用程序大小时动态扩展它。
  • 我不明白。 WPF 本质上与分辨率无关。你为什么要申请ScaleTransform
  • 在 WPF 中,它们是 Windows 或 Pages - 而不是表单。我认为你把事情弄得太复杂了。
  • @Blam 我讨厌他们将Window 称为“表单”。

标签: c# wpf data-binding layouttransform


【解决方案1】:

WPF is Resolution Independent by nature.

<Window ..>
   <Grid>

   <!-- Content here -->

   </Grid>
</Window>

上述 XAML 将导致 Grid 拉伸到窗口大小。不需要可怕的类似 winforms 的 hack。

编辑:

如果您希望 Everything(包括字体大小)在 Window 内缩放,只需使用 Viewbox:

<Window>
   <Viewbox>
       <Grid>

       <!-- Content here -->

       </Grid>
   </Viewbox>
</Window>

【讨论】:

  • 里面的所有元素呢?他们会扩大规模吗?字体会缩放吗?我发现 ScaleTransform 运行良好的主要原因是因为我有几个框架,其中包含不同的页面。
  • 是的,修复了它。哇。我不敢相信我忽略了将整个网格放在一个视图框中。
【解决方案2】:

最简单的解决方案是使用 Viewbox,但也可以非常简单地计算 Window resize 的比例。

视图框

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Viewbox Stretch="Uniform">
    <Grid>
        <Label>
            Hello world
        </Label>
    </Grid>
</Viewbox>
</Window>

手动缩放

<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>

使用 LayoutTransform 来缩放网格,该 LayoutTransform 通过引用编码的 ScaleValue 依赖属性来确定 ScaleX 和 ScaleY 属性,该依赖属性是在 Window_Resize 事件期间使用类似代码的代码计算的

#region ScaleValue Dependency 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;
    }

    public double ScaleValue
    {            
        get
        {
            return (double)GetValue(ScaleValueProperty);
        }
        set
        {
            SetValue(ScaleValueProperty, value);
        }
    }
    #endregion


    private void CalculateScale()
        {
            double yScale = ActualHeight / 250f;
            double xScale = ActualWidth / 200f;
            double value = Math.Min(xScale, yScale);
            ScaleValue = (double)OnCoerceScaleValue(MainGrid, value);
        }

【讨论】:

  • 如果我没记错的话,viewbox 的问题是单个 viewbox 只能容纳一个元素。虽然现在这可能可行,因为我们使用框架来保存我们的页面。
  • @Herrozerro 如果您“显示多个页面”(无论这意味着什么),只需在 Viewbox 中放置一个 ContentPresenter 并绑定 Content 属性。我看不出你想在过程代码中做这件事有什么大不了的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
  • 2012-06-02
  • 2011-11-10
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
相关资源
最近更新 更多